0% found this document useful (0 votes)
1K views

SFC Developer's Guide: Release 4.5.X 23 November 2007 Doc ID: SDK453UMC++.070

Reuters does not guarantee that any information contained herein is and will remain accurate or that use of the information will ensure correct and faultless operation of the relevant service or equipment. This manual is subject to U.S. Export regulations.

Uploaded by

Pauli Yang
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1K views

SFC Developer's Guide: Release 4.5.X 23 November 2007 Doc ID: SDK453UMC++.070

Reuters does not guarantee that any information contained herein is and will remain accurate or that use of the information will ensure correct and faultless operation of the relevant service or equipment. This manual is subject to U.S. Export regulations.

Uploaded by

Pauli Yang
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 423

SFC Developer’s Guide

Release 4.5.X
23 November 2007
Doc ID: SDK453UMC++.070
Copyright © 1995, 1996, 1998, 2000-2007 Reuters Group plc. All rights reserved.
Except as permitted by law no part of this document may be reproduced or transmitted by any process or means
without the prior consent of Reuters Group plc.
Reuters, by publishing this document, does not guarantee that any information contained herein is and will remain
accurate or that use of the information will ensure correct and faultless operation of the relevant service or
equipment. Reuters, its agents and employees shall not be held liable to or through any user for any loss or
damage whatsoever resulting from reliance on the information contained herein.
This document refers to the products and trademarks of manufacturers. Acknowledgment is made of all
trademarks, registered trademarks and trading names that are referred to in the text.
TIB is a registered trademark and TIBCO and TIBCO Rendezvous are trademarks of TIBCO Software Inc.
REUTERS, the Sphere Logo, Triarch, and Reuters SSL are trademarks of the Reuters Group of Companies round
the world.
This SOFTWARE, including but not limited to, the code, screen, structure, sequence, and organization thereof,
and DOCUMENTATION are protected by United States copyright laws and international treaty provisions.
This manual is subject to U.S. export regulations.
TABLE OF CONTENTS

1 OVERVIEW 1
1.1 What are the System Foundation Classes? 1
1.2 Audience 1
1.3 Organization of the SFC Documents 1
1.4 Conventions 3
1.4.1 Typographic 3
1.4.2 Programming 3
1.4.3 Naming 4
1.5 The SFC Development Process and Change Management Policies 5
1.6 Scope and Availability 6

2 DESIGN PHILOSOPHY 7
2.1 Modeling Principles 7
2.2 Design by Contract 8
2.3 Component Design 9
2.4 Application Design 10

3 THE SFC APPLICATION FRAMEWORK 11


3.1 Market Data Items and Services 11
3.2 Market Data Clients 12
3.3 Application Structure 12
3.3.1 Data and State Events 12
3.3.2 System Events 13
3.4 Threading and Exceptions 14

4 SFC MODELS 15
4.1 Record Subscription 15
4.1.1 Overview 15
4.1.1.1 Record Items 15
4.1.1.2 Real-time Records 16
4.1.1.3 Snapshot Records 16
4.1.1.4 Record Chains 17
4.1.1.5 Record Services 17
4.1.1.6 Record Service Pools 18

SFC Developer’s Guide iii


Contents

4.1.1.7 Client Classes 19


4.1.2 Design 19
4.1.2.1 Real-time Record State 19
4.1.2.2 Snapshot Record State 22
4.1.2.3 Record Chain State 24
4.1.2.4 Service State 28
4.1.2.5 Record Client Management 29
4.1.2.6 Record Clients 31
4.1.2.7 Access to Fields 33
4.1.2.8 Field Updates 34
4.1.3 Implementation 35
4.1.3.1 Multiple Services 36
4.1.4 Class Summaries 36
4.1.4.1 Real-time Record Class Summary 37
4.1.4.2 Snapshot Record Class Summary 38
4.1.4.3 Record Chain Class Summary 39
4.1.4.4 Summary of Other Classes in the Record Cluster 39
4.1.5 Examples 40
4.1.6 Record Snapshot Client 41
4.1.6.1 Declaration of RecordSnapshotClient 42
4.1.6.2 Definition of RecordSnapshotClient 43
4.1.6.3 RecSnap Application 46
4.1.7 Real-time Record Client 47
4.1.7.1 Declaration of RecordUpdateClient 48
4.1.7.2 Definition of RecordUpdateClient 49
4.1.7.3 RecUpd Application 52
4.1.8 Field Client 53
4.1.9 Pool Client 53
4.1.9.1 Declaration for TickerMonitor (tickmon.h) 53
4.1.9.2 Definition of TickerMonitor (tickmon.C) 55
4.1.10 Chain Client 58
4.1.10.1 ChainElementRecordClient 59
4.2 Record Publication 61
4.2.1 Overview 61
4.2.1.1 Published Records 61

SFC Developer’s Guide iv


Contents

4.2.1.2 Publishing Service 62


4.2.2 Design 63
4.2.2.1 Record Creation 63
4.2.2.2 Record State Diagram 65
4.2.2.3 Record State Change Events 66
4.2.2.4 Record Data Change Events 68
4.2.2.5 Record Initialization 69
4.2.2.6 Updating Fields in a Published Record 71
4.2.2.7 Changing Record State 72
4.2.2.8 Resynchronizing Record Data 73
4.2.2.9 Access to Published Records 73
4.2.2.10 Publishing Service State Changes 74
4.2.2.11 Publishing Entitlement Data 77
4.2.2.12 Managing Record Resources 79
4.2.3 Class Summary 80
4.2.4 Implementation 82
4.2.4.1 SSL Publishing Service 83
4.2.4.2 TIB Publishing Service 85
4.2.4.3 In-Process RTRRTRecordService Publisher 86
4.2.5 Examples 87
4.2.6 Simulator Program 90
4.2.6.1 Requirements 90
4.2.6.2 Design and Implementation 91
4.2.6.3 SimulatedService Class Declaration 92
4.2.6.4 SimulatedService Class Definition 93
4.2.6.5 FullCacheSimulatedService Class 95
4.2.6.6 SimulatedRecord Publisher Class Declaration 97
4.2.6.7 SimulatedRecord Class Definition 99
4.2.6.8 Creating an Application 111
4.2.7 Gateway Example 118
4.2.7.1 Requirements 118
4.2.7.2 Design and Implementation 118
4.2.7.3 GatewayService Class Declaration 119
4.2.7.4 GatewayService Class Definition 121
4.2.7.5 SinkDrivenGatewayService Class Declaration 124

SFC Developer’s Guide v


Contents

4.2.7.6 SinkDrivenGatewayService Class Definition 125


4.2.7.7 SourceDrivenGatewayService Class Declaration 127
4.2.7.8 SourceDrivenGatewayService Class Definition 128
4.2.7.9 GatewayRecord Class Declaration 130
4.2.7.10 GatewayRecord Class Definition 132
4.3 Page Subscription 141
4.3.1 Overview 141
4.3.1.1 Pages 141
4.3.1.2 Logical Pages 141
4.3.1.3 Attributes 142
4.3.1.4 Services and Service Pools 143
4.3.2 Design 143
4.3.2.1 Page State 143
4.3.2.2 Service State 144
4.3.3 Class Summary 144
4.3.4 Implementation 146
4.3.4.1 Character Sets 146
4.3.4.2 Attribute Mapping 146
4.3.4.3 Configuration 147
4.3.4.4 Multiple Services 147
4.3.5 Examples 147
4.3.6 Page Client 148
4.3.6.1 Declaration of PageUpdClient (pageupdclient.h) 149
4.3.6.2 Definition of PageUpdClient (pageupdclient.C) 150
4.3.6.3 Creating Page Service and PageUpdClient 152
4.3.7 Region Client 153
4.3.7.1 Definition of RegionUpdClient (regionupdclient.C) 153
4.3.8 Attribute Examples 154
4.4 Page Stream Subscription 156
4.4.1 Overview 156
4.4.1.1 Page Streams 156
4.4.1.2 Services 156
4.4.1.3 Service Pools 157
4.4.2 Design 157
4.4.2.1 Page State 157

SFC Developer’s Guide vi


Contents

4.4.2.2 Service State 158


4.4.3 Class Summary 158
4.4.4 Implementation 159
4.4.5 Examples 159
4.4.6 Example Class — Simple Page Client 160
4.4.6.1 Declaration of AnsiPageSnapshotClient (ansipagesnapclient.h) 161
4.4.6.2 Definition of AnsiPageSnapshotClient (ansipagesnapclient.C) 162
4.4.7 Example Application — ANSI Page Snapshot 165
4.4.8 Example Class — ANSI Page Updates 167
4.4.8.1 Declaration of AnsiPageUpdClient (ansipageupdclient.h) 167
4.4.8.2 Definition of AnsiPageUpdClient (pageupdclient.C) 169
4.5 Time-Series 172
4.5.1 Overview 172
4.5.1.1 Time-Series 172
4.5.1.2 Time-Series Services 173
4.5.1.3 Simple Series 173
4.5.2 Time-Series State Diagram 173
4.5.3 Class Summary 175
4.5.4 Implementation 176
4.5.4.1 Multiple Services 177
4.5.5 Examples 177
4.5.6 TSDump Example 178
4.5.6.1 Declaration of TSClientByCount (tsbycount.h) 179
4.5.6.2 Definition of TSClientByCount (tsbycount.C) 180
4.5.6.3 Example Application — Time-Series 182
4.5.6.4 Example Code — ostream Output Methods 184
4.5.7 TSDates Example 186
4.5.7.1 Declaration of TSClientByDate (tsbydate.h) 186
4.5.7.2 Definition of TSClientByDate (tsbydate.C) 187
4.5.8 TSAvg Example 189
4.5.8.1 Declaration of SimpleSeriesClient (simpleclient.h) 190
4.5.8.2 Definition of SimpleSeriesClient (simpleclient.C) 191
4.6 Inserts 193
4.6.1 Overview 193
4.6.2 Insert Items 193

SFC Developer’s Guide vii


Contents

4.6.3 Insert Services 194


4.6.3.1 Insert Service Pools 194
4.6.4 Insert Request Server 194
4.6.5 Example Class — Insert Server 195
4.6.5.1 Creating an Application 195
4.6.5.2 Example Class — Insert Client 196
4.6.5.3 Declaration for SimpleInsertExample (siminsrt.h) 196
4.6.5.4 Definition for SimpleInsertExample (siminsrt.C) 198
4.6.6 Example Application — Inserts 201
4.7 Session 203
4.7.1 Message Session 203
4.7.1.1 The Model 203
4.7.1.2 Message Session Abstraction 204
4.7.2 Example — Simple Message Session Clients 205
4.7.2.1 Basic Requirements for Reply Class 205
4.7.2.2 Declaration for Reply (reply.h) 206
4.7.2.3 Definition for Reply (reply.C) 207
4.7.3 Example — Another Simple Message Session Client 211
4.7.3.1 Declaration for Request (request.h) 211
4.7.3.2 Definition for Request (request.C) 213
4.7.4 TCP/IP Socket Implementation of Message Session 217
4.7.4.1 The Model 217
4.7.4.2 TCP Session Server Event Client Types 218
4.7.5 Example — A Simple TCP Session Server Client 219
4.7.5.1 Declaration for Reply Server (replysvr.h) 219
4.7.5.2 Definition for Reply Server (replysvr.C) 221
4.7.6 Example — A Simple Application Using ReplyServer 222
4.7.7 Example — A Simple Application Using a TCP Client Session 223
4.8 Support 226
4.8.1 Connection 226
4.8.1.1 Overview 226
4.8.1.2 Implementation 227
4.8.1.3 Examples 227
4.8.2 Service Pool Factory 228
4.8.2.1 Overview 228

SFC Developer’s Guide viii


Contents

4.8.2.2 Implementation 229


4.8.2.3 Examples 229
4.8.3 Event Loop 235
4.8.3.1 I/O Events 236
4.8.3.2 Timer Events 236
4.8.3.3 Custom Event Loop 237
4.8.4 Example — I/O and Timing 237
4.8.4.1 Declaration of IOTimerClient (iotimerclient.h) 238
4.8.4.2 Definition of IOTimerClient (iotimerclient.C) 239
4.8.4.3 Example Application - Select based (selecttest.C) 240
4.8.4.4 Example Application - Xt based (xttest.C) 241
4.8.4.5 Example Application - XView based (xvtest.C) 243
4.8.5 Configuration 244
4.8.5.1 Overview 244
4.8.5.2 Assigning Class Identifiers 245
4.8.5.3 Assigning Instance Identifiers 246
4.8.5.4 An Implementation Using X-Window Resource Files 247
4.8.5.5 RTRXFileDb Example 247
4.8.5.6 An Implementation Using the Microsoft Windows NT Registry 249
4.8.5.7 RTRRegistryDb Example 250
4.8.5.8 Global Access using RTRConfig 252
4.8.6 Event Logging 253
4.8.6.1 Overview 253
4.8.6.2 Implementation Classes 254
4.8.6.3 Simple Example 254
4.8.6.4 Configuration Examples 255
4.8.7 Command Line 257
4.8.7.1 Overview 257
4.8.7.2 Usage 258
4.8.8 Class Summary 259
4.8.8.1 Connection 259
4.8.8.2 Service Pool Factory 260
4.8.8.3 Control Loop 260
4.8.8.4 Configuration 261
4.8.8.5 Event Logging 262

SFC Developer’s Guide ix


Contents

4.8.8.6 Command Line 262


4.8.8.7 International Characters 263

5 SFC IMPLEMENTATION DETAILS 264


5.1 SSL and TIB Implementations 264
5.2 Implementation Classes 265
5.3 Entitlements 266
5.3.1 Supported Configurations 267
5.3.2 Enabling Data Entitlements in SFC 268
5.3.3 Setting the Username 270
5.3.4 Publishing DACS Access Locks 272
5.3.5 DACS Implementation Details 273
5.3.5.1 DACS Thread Aware Option 275
5.3.6 Entitlements Configuration 276
5.4 Performance Tuning and Tracing 278
5.4.1 General Guidelines 278
5.4.1.1 Use Libraries Without Assertion 278
5.4.1.2 Disable Tracing 278
5.4.2 Optimizing Code 279
5.4.2.1 Accessing a Market Data Item from a Service 279
5.4.2.2 Accessing a Field from a Record 280
5.4.2.3 Setting the Contents of a Field 280
5.4.2.4 Sending an Image or an Update 282
5.4.3 Reducing Memory Usage 282
5.4.3.1 Use SFC’s Cache 282
5.4.3.2 Reducing Consumer Memory 283
5.4.3.3 Reducing Publisher Memory 283
5.4.4 Request Queueing and Timing 283
5.4.4.1 Request Queue 284
5.4.4.2 Request Timing 285
5.4.4.3 Configuration 285
5.4.5 Image Publishing 286
5.4.5.1 Relationship between SFC and Source Distributor Cache Size 286
5.4.5.2 Source-Driven Publishers 287
5.4.5.3 Image Pacing 287

SFC Developer’s Guide x


Contents

5.4.5.4 Performance and Record Templates 288


5.4.6 Tracing 288
5.4.6.1 RMDS/TIB/SSL Publishing and RMDS/TIB Subscription 288
5.4.6.2 SSL Subscription 289
5.4.7 Low-level Tracing and Error Messages 289
5.5 Implementation Issues 291
5.5.1 Cross-infrastructure Compatibility 291
5.5.2 Data Format 292
5.5.2.1 Enumerations 293
5.5.2.2 Hint 296
5.5.3 Record Templates 300
5.5.4 Data Dictionary 301
5.5.4.1 Sharing a Data Dictionary 302
5.5.4.2 Infrastructure Issues 303
5.5.4.3 Examples 304
5.5.4.4 Configuration 306
5.5.5 Data and Connection Status 307
5.5.5.1 Data Status with TIC and RTIC 307
5.5.5.2 Rendezvous Advisory Messages 308
5.5.5.3 SSL Warning Messages 309
5.5.5.4 Status Event Normalization 310
5.5.6 Discovery 310
5.5.6.1 Service Pool Factory 310
5.5.6.2 Service Provider Discovery 311
5.5.7 Market Data Item Names and TIB Subject Names 312
5.5.7.1 RIC to Subject Mapping 314
5.5.7.2 Default Customizers 316
5.5.7.3 Setting defaultSector to "." 317
5.5.7.4 Overriding the TIB Customizer 318
5.5.7.5 Next and Previous Page Names 320
5.5.7.6 News Headlines 320
5.5.7.7 Configuration 321
5.5.8 Page Services 322
5.5.8.1 Page Records 322
5.5.8.2 Effects Page Attribute Encoding 323

SFC Developer’s Guide xi


Contents

5.5.8.3 ANSI Page Sizes 323


5.5.9 Inserts and Contributions 324
5.5.9.1 Inserts and Triarch 324
5.5.9.2 Inserts and RMDS (SASS3) 324
5.5.9.3 Inserts and Classic TIB (SASS2 and SASS3) 324
5.5.10 Connection Parameters 325
5.5.10.1 TIB 325
5.5.10.2 SSL 327
5.5.11 Using Rendezvous 6 Library with the SFC 328
5.5.12 Using Rendezvous 5 Library with the SFC 328
5.6 Configuration 330
5.6.1 SSL Library Configuration 330
5.6.2 SFC Configuration Summary 330

APPENDIX A: GLOSSARY 339

APPENDIX B: TRIARCH INFRASTRUCTURE 348


B.1 Overview 348
B.2 The SSL Interface 348
B.3 SSL Sink Components 350
B.3.1 The Sink Application 350
B.3.2 Sink Distributor 351
B.4 Design Goals and System Features 352
B.4.1 Triarch System Design Goals 352
B.4.2 Reliable Data Communications 352
B.4.3 Flexibility and Scalability 353
B.4.4 Optimal Resource Usage 353
B.4.5 Fault Tolerance and Resiliency 354
B.4.6 Single Item Open Request 355
B.4.7 Management and Monitoring of Status 355
B.4.8 Data Access Control 355
B.5 Request Routing and Resource Optimization 355
B.5.1 Basic Request Routing without the Optional Service Distributor 355
B.5.2 Full Resource Management and Request Routing with the
Service Distributor 358

SFC Developer’s Guide xii


Contents

B.5.3 System Resiliency (“Failover”) 359


B.6 SSL Library Configuration 361
B.6.1 Overview 361
B.6.2 File Entry Rules and Formats 361
B.6.2.1 Location of the File 361
B.6.2.2 Special Configuration File Entry Characters 361
B.6.2.3 Configuration File Entry Format 361
B.6.2.4 Binding of Configuration Entries 362
B.6.2.5 Order of Precedence 363
B.6.2.6 Updating the Configuration File 363
B.6.3 Valid Configuration File Parameters 363
B.6.3.1 eventLogging 363
B.6.3.2 functionLogging 364
B.6.3.3 ipcConnectionTimeout 364
B.6.3.4 ipcRoute 364
B.6.3.5 ipcRouteName 365
B.6.3.6 ipcServer 366
B.6.3.7 maxMounts 366
B.6.3.8 maxProcessBuffers 367
B.6.3.9 maxRemountDelay 367
B.6.3.10 maxUnconfirmedMsgs 367
B.6.3.11 messageTracing 368
B.6.3.12 messageTracingFlags 368
B.6.3.13 minRemountDelay 368
B.6.3.14 msgMountDelimiter 369
B.6.3.15 numInputBuffers 369
B.6.3.16 numOutputBuffers 369
B.6.3.17 pingInterval 370
B.6.3.18 serviceId 370
B.6.3.19 snkResponseThrottle 371
B.6.3.20 tcpQuickAck 371
B.6.4 Sample Configuration File 372

APPENDIX C: TIB INFRASTRUCTURE - SASS2 374


C.1 Overview 374

SFC Developer’s Guide xiii


Contents

C.2 Architecture 374


C.2.1 TIC-based Publish/Subscribe 374
C.2.2 Publishing to Support ciServer Subscribers 375
C.2.3 Configuration 376

APPENDIX D: TIB INFRASTRUCTURE - SASS3 378


D.1 Overview 378
D.2 Architecture 378
D.2.1 TIB-Based Publisher 379
D.2.2 TIB-Based Consumer 379
D.3 TMF 379
D.4 Configuration 380

APPENDIX E: RMDS INFRASTRUCTURE 383


E.1 Overview 383
E.2 Architecture 383
E.2.1 SSL-Based Publisher 385
E.2.2 TIB-Based Publisher 385
E.2.3 TIB-Based Consumer 385
E.3 TMF 386
E.4 Configuration 388

APPENDIX G: DACS LIBRARY FUNCTIONS 391


G.1 DACS_CsLock() 391
G.2 DACS_GetLock() 394
G.3 DACS_CmpLock() 397
G.4 DACS_perror() 399

SFC Developer’s Guide xiv


1 OVERVIEW
1.1 What are the System Foundation Classes?
The System Foundation Class (SFC) Library is a collection of C++ classes which model the problem
domain of financial information systems. The purpose of the SFC is to provide a suite of clearly
defined, easy to use conceptual models, or abstractions. These abstractions represent the
fundamental data types of interest to applications and also the infrastructure necessary to create both
libraries and applications. By using SFC abstractions, applications can easily be written to work on
more than one type of market data infrastructure.
NOTE: The TIB Legacy products are no longer supported by SFC v.4.5.1.L3 onwards.

1.2 Audience
Users of the SFC Library should have working knowledge of the C++ language and a general
understanding of the concepts of object-oriented analysis and design.
Some useful books for learning C++ are:
[1] Object-Oriented Programming using C++ by Ira Pohl, ISBN #:0-8053-5382-8
[2] Effective C++ by Scott Meyers, ISBN #: 0-201-56364-9
[3] Advanced C++ - Programming Styles and Idioms by James O. Coplien, ISBN# 0-204-54855-0
Some useful books for learning object-orientated concepts are:
[4] Object-Oriented Software Construction by Bertrand Meyer, ISBN #: 0-13-629049-3
[5] Object-Oriented Analysis and Design by Grady Booch, ISBN #:0-8053-5340-2
[6] Design Patterns by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, ISBN
#0-201-65561-2

1.3 Organization of the SFC Documents


The SFC documentation is divided into three manuals, this Developer’s Guide, a Migration Guide and
a Reference Manual. The purpose of the Developer’s Guide is to provide an introduction to the SFC, to
convey to the developer a sense of the philosophy behind the SFC, and to provide details on the
primary SFC models.

SFC Developer’s Guide 1


1 OVERVIEW

The remaining sections in this chapter discuss the conventions used in the manual, the SFC
development process, and the current scope of the product.

Chapter 2 Design Philosophy Gives an overview of the object-oriented principles


which have a bearing on library design and application
structure.
Chapter 3 SFC Application Describes how these principles are applied in the SFC
Framework and introduces the SFC application framework.
Chapter 4 SFC Models Presents cluster overviews of the various SFC models.
These overviews describe each of the primary models
which comprise the SFC, identifying the essential
classes and giving one or more examples of their
usage.
Chapter 5 SFC Implementation Discusses some of the differences between the infra-
Details structures and details some important implementation
and usage issues.
Appendix A Glossary Defines key terms used in this manual.
Appendix B Triarch Infrastructure Provides overview of Triarch/SSL infrastructure.
Appendix C TIB Infrastructure - SASS2 Provides overview of TIB infrastructure configured to
use SASS2 protocol..
Appendix D TIB Infrastructure - SASS3 Provides overview of TIB infrastructure configured to
use SASS3 protocol.
Appendix E RMDS Infrastructure Provides overview of RMDS infrastructure.
Appendix G DACS Library Functions Contains the DACS-specific function calls needed for
DACS-compliant sources to perform subservice and
compound permissioning.

The SFC Migration Guide details the differences between the SFC in SSL Developers Kit - Classic
Edition 4.0.x and this release of SFC. It also describes what changes will need to be made when
migrating programs.

SFC Developer’s Guide 2


1 OVERVIEW

The SFC Reference Manual contains a class reference with detailed descriptions of each class in the
SFC.
Also included with the SFC documentation is the Reuters Marketfeed Reference Manual which defines
the syntax of those Marketfeed messages that may be sent by source applications or received by sink
applications.
The SFC documentation does not cover the installation and configuration of the Triarch and RMDS
market data infrastructures. Consult the product documentation of those infrastructures for information
on market data components, including RVD, and Sink, Source and Service Distributors.

1.4 Conventions

1.4.1 Typographic
• Important notes and tips are marked off with a box.

NOTE: These tips can be helpful.

• Function names appear in a bold text font; e.g.


addClient()
• Samples of code appear in a typewriter font; e.g.
RTRRTField *trdprc1;
RTRRTField *volume;
char *value;
• File names appear in a bold italic font; e.g.
filename

NOTE: Most files referenced in this document with a .C extension will have a .cpp extension in
the win32 load.

1.4.2 Programming
• All class names start with the letters “RTR” (for ReuTeR classes; e.g. RTRString).

SFC Developer’s Guide 3


1 OVERVIEW

• All function names start with lower case letters, but subsequent words are capitalized (e.g.,
append() and lastString()).
• In order to make function names easy to understand, abbreviations are used sparingly. Some
class names may seem rather long, but these names should be easier to understand than
abbreviated names. On the technical side, it is important that class names do not clash with other
class libraries or client defined classes. The combination of the “RTR” prefix and the long name
format will avoid name collisions with classes from other libraries.
• To provide consistent, easy to learn class interfaces, function names are assigned such that
functions are given the same name in different classes if they have the same use. Application
developers will be able to understand new classes more quickly when the naming is consistent.
For instance, the addClient() function is used throughout the real-time classes as the mechanism
that allows components to register for events.
• The SFC uses a common boolean type RTRBOOL, which can have either RTRTRUE or
RTRFALSE as its value.
• Where class methods return a pointer, the return value may be null. In circumstances where
returned values will never be null, an object reference will be returned.
• The SFC uses the following memory management guideline: “If you allocated the object, you
delete it. If you didn’t allocate the object, don’t delete it.” Any exceptions to the guideline will be
explicitly highlighted in the appropriate section(s) of the SFC Reference Manual. When possible,
objects should be deleted in the reverse order from which they were allocated.

1.4.3 Naming
SFC originally only included an implementation for the Triarch (SSL) infrastructure. While the SFC
name originates from SSL Foundation Classes, the core part of SFC, the abstract models, is generic
for any market data infrastructure. So even though SFC now includes a TIB implementation for TIC-
based TIB and Reuters Market Data System (RMDS) infrastructures, the name “SFC” applies to the
abstract models of both implementations.
The class names for Triarch and RMDS (P2PS, MDH) implementation included “SSL” and “Default.”
These classes retain those names for backwards compatibility. The class names for the TIB
implementation include “TIB.” Through the rest of this document, “SSL” refers to the implementation
for the Triarch infrastructure and RMDS (P2PS, MDH), and “TIB” refers to the implementation for the
RTIC-based RMDS infrastructure. “TSA” is used in implementations that work only with the RMDS
Distribution Layer.

SFC Developer’s Guide 4


1 OVERVIEW

SFC’s TIB implementation should be used when consuming data from RMDS. Both the SSL and the
TIB record publishing implementations can be used with an RMDS infrastructure. The TSA insert
implementation can be used to contribute to an RMDS infrastructure. See Figure E.1 for more
information.
The TIB implementation is designed to work with TIBCO Rendezvous, so it is used with the
Rendezvous Distribution Layer of RMDS. However, due to subtle differences in the infrastructures,
SFC must be told which infrastructure it is using. See section 4.8.1 and section 4.8.2 for information on
how to do this.

NOTES:
• When this document, the SFC Reference Manual, or the example programs refer to “TSA”
(Trading Solution Architecture) they are referring to RMDS. In that context, the terms TSA and
RMDS are interchangeable.
• The TIB implementation is designed to work with the RTIC-based RMDS infrastructure.

1.5 The SFC Development Process and Change Management Policies


SFC models and classes are developed under the assumption that they are not correctly defined until
proven useful in practical applications. Development is based on an iterative life-cycle. Validation of a
new model requires both multiple uses of the library and multiple implementations. The latter ensures
that the abstract interfaces are sufficiently independent of implementation details. The former ensures
that the library is useful as well as abstract. Not all implementations which result from this process are
part of the delivered product.
Often, much of the required iteration is the result of internal usage. However, it is usually the case that
external clients provide the final validation of a new library component prior to release of the product.
Several of the models in the current product have been through several generations, others are much
newer.
Users of the SFC should be prepared for some degree of change especially when using the newer
models. Every effort is made to ensure that, where possible, changes are backwards compatible with
existing software, but such compatibility is not always possible. When the interface of a model
changes, its old methods are marked “OBSOLETE.” These methods could be obsolete because they
did not function correctly in all circumstances or just because the naming has been changed for model
consistency. In the later case, the obsolete methods may still be used in legacy code. To ensure
backwards compatibility, they remain implemented and should be implemented in new subclasses.

SFC Developer’s Guide 5


1 OVERVIEW

Users of the SFC are strongly encouraged to provide feedback on both the conceptual models and the
implementation.

1.6 Scope and Availability


Currently, the SFC provides abstractions for:
• subscribing to and publishing real-time record data
• subscribing to real-time page data
• retrieving historical (time-series) data
• contributions
• session-based communication
• various supporting models, including: the application control loop, configuration, event logging,
service pool management, and peer-to-peer interprocess communication facilities.
New models will be added in the future.
The SFC is available on Win32 and Solaris. Additional platforms will be supported on the basis of
demand. Please contact your Reuters representative for exact details on current availability.

SFC Developer’s Guide 6


2 DESIGN PHILOSOPHY
2.1 Modeling Principles
The SFC Library is based on a conceptual model of the problem domain which comprises financial
market data.
The purpose of developing an abstract model is to ensure that software components are properly
isolated from non-essential characteristics of their suppliers. The effect of this approach is to de-couple
the various parts of an application or system and provide simpler, more intuitive programmatic
interfaces. In practice, it also means that components can be more easily maintained (they can be re-
worked with no impact on other parts of the system), and they can also be readily exchanged with
“like” components making systems more adaptable to changing requirements.
Effective models provide abstraction and encapsulation, and exhibit modularity. Booch [5] defines
these terms as follows:
Abstraction - “An abstraction denotes the essential characteristics of an object that distinguish it
from all other kinds of object and thus provide crisply defined conceptual boundaries, relative to
the perspective of the viewer.”
Encapsulation - “Encapsulation is the process of compartmentalizing the elements of an
abstraction that constitute its structure and behavior; encapsulation serves to separate the
contractual interface of an abstraction and its implementation.”
Modularity - “Modularity is the property of a system that has been decomposed into a set of
cohesive and loosely coupled modules.”
How is a model developed? Development of a model starts with an analysis of the problem domain. If
expertise is not available, knowledge must be gained through experimentation. Regardless of the
technique used, analysis yields a complete theoretical model of the components to be found in the
problem domain and is represented by a set of abstract data types.
Conceptual models are rarely correct the first time. Through trial and error a model evolves over time,
gradually becoming stable. Stability is achieved through practical application of the model in building
systems, both through using the interface defined by the model and by implementing the data types
required by the model.
A model can be defined by English text (or some other natural language mechanism), by a formal
modeling language, by a programmatic interface, or by some combination of these techniques. All of
these techniques have advantages and disadvantages. What is important is to have a comprehensive
description of the model which can then be used to provide programmatic implementations.

SFC Developer’s Guide 7


2 DESIGN PHILOSOPHY

Ultimately, application programming interfaces (APIs) are required. When using an object-oriented
programming environment, the result is a set of class libraries. A given model may have more than one
implementation. The models which comprise a class library must be modular in their design and
implementation. That is, it must be possible to add and remove both models and implementations
thereof. This allows the scope of the library to grow and change over time in a manageable fashion.
Why go to all the trouble of developing abstract data types, iterating through prototypes, and building
components? Clearly, the production of a reusable component requires high standards of design and
implementation, and, perhaps, imposes restrictions on the way in which software can be implemented.
Perhaps the most important benefit of building components is the flexibility it affords. Components can
be swapped out, enhanced, maintained, and interchanged. Monolithic software systems inhibit
maintenance and enhancement.
Additionally, a well conceived conceptual model affords a much friendlier, more intuitive programming
environment, letting programmers concentrate on problems specific to their particular domain rather
than having to master the details of many different domains and implementations.

2.2 Design by Contract


In many of the class function descriptions, you will notice the terms “REQUIRE” and/or “ENSURE”
along with some conditional code. These statements, or assertions, suggest a contract between the
client (caller) and supplier such that if the client fulfills the required preconditions, then the supplier will
ensure that the postconditions will be true upon return from the function.
This method of programming is more commonly known as “design by contract” and is used not only in
the abstract interfaces described in the manuals but is also used extensively throughout the SFC
implementation.
Assertions are programmed into the library code using macros that are based on the standard “assert”
mechanism. The SFC distribution provides two versions of each library—one with assertions, one
without. Client programmers have the option to link their applications with either version. There is
some performance penalty for using the version with assertions. Typically users of the library will link
with assertions while developing and debugging their code, then use the non-assertion version for their
finished product.
If an assertion statement fails during execution, the program will exit and print out the condition that
failed, the name of the file the assertion failed in and the line number of the assertion in the file. This
typically provides a good starting point for tracing back to determine where the problem originated.

SFC Developer’s Guide 8


2 DESIGN PHILOSOPHY

The following is an example of the use of assertions:


RTRBOOL hasClient(RTRRTRecordClient&) const;
Is the given client registered to receive events?
void addClient(RTRRTRecordClient& newClient);
Register the given client to receive events.
!hasClient(newClient)
hasClient(newClient)
In this example, the addClient() is used to register a new client. The assertions explain that a given
client may register only once (REQUIRE: !hasClient) and that following the call to addClient(), the
given client will be registered (ENSURE: hasClient).
One more example:
RTRBOOL hasFieldByname(const char *name) const;
Does this record contain a field with the given name?
RTRRTField *fieldByName(const char *name) const;
The field with the given name.
(result == 0) == (hasFieldByName(name))
(result == 0) || result->name() == name
In the postconditions, the term “result” means the value returned from the function. Therefore, the
assertions explain that if the record contains the field with the given name, fieldByName() will return a
pointer to that field, otherwise, it will return a null pointer.

2.3 Component Design


Components are pieces of software which are designed to be reusable. As such, they must be
independent of context. In other words, components must be independent of application specific
assumptions. In particular, components should rely on the abstract interfaces of other software
suppliers and be as independent as possible of implementation details.
In general, components should be single purpose. This means that they tend to be simple and
modular. The SFC market data abstractions and other models support this philosophy and are
themselves implemented in accordance with it.
One example of a component which might be constructed using the SFC is a quote display. An
application-independent quote display component would use the abstract interfaces to the SFC real-

SFC Developer’s Guide 9


2 DESIGN PHILOSOPHY

time record model to retrieve a record item. It would need access to formatting information specifying
which fields to display, where to display them, and which presentation attributes to use in doing so.
Ideally, this component is independent of the particular user interface being used and also
independent of the display technology.
Another example is a limit minding component which monitors fields from a record and tests whether
those fields exceed predefined limits. Ideally, this kind of capability is implemented so that it is
independent of display and user interface.

2.4 Application Design


Applications are collections of components which together provide the required functionality.
Application designers decide which components are necessary and also, either at compile time or link
time, which implementations of abstract models to use. In contrast to components, which are
implementation independent, applications tend to be implementation specific.

SFC Developer’s Guide 10


3 THE SFC APPLICATION FRAMEWORK
3.1 Market Data Items and Services
Financial information systems represent a complex problem domain. Applications in this domain must
potentially process many different types of market data. The data is often available in several different
formats. Not only are there many types and formats of data, there are also many data suppliers. The
semantics and format of the raw data must be understood by the application developer.
In addition, applications often must operate as part of a distributed system. This further increases the
complexity and means that the developer must learn network protocols or the APIs which provide
access to network based services.
The purpose of most applications developed for this environment is to manipulate and/or present the
underlying market data. The purpose of the SFC is to make this task easier by providing intuitive, easy-
to-use, and implementation-independent interfaces to market data.
The SFC does this by providing a number of different models corresponding to the fundamental data
types of interest to applications. These models capture semantics of the underlying data types but
shield applications from the details of retrieving the data.
The primary component of SFC market data models is the data item. Data items correspond to the
underlying units of financial information which are of interest to application programmers. Typical SFC
applications are concerned primarily with abstract representations of item state, events, and data
content, rather than implementation-specific issues such as network messages and encoding syntax.
Data items represent a particular financial instrument or collection of data, and are retrieved from a
service (e.g., Reuters Selectserver) by a name (e.g., DEM=) which is unique in the context of that
service.
• Items are typically pages or records, but the system does not preclude other data types.
• Items may be in different states (e.g., OK, STALE) and may undergo changes in state. The state
of a data item from the perspective of a particular sink application can be thought of as a logical
connection.
• Items may have priority relative to other items.
• Items may be permissioned to control access.
A secondary concept in the SFC market data models is the provider of data items, usually referred to
as a service. Services are the abstraction which encompass the distributed nature of the problem

SFC Developer’s Guide 11


3 THE SFC APPLICATION FRAMEWORK

domain. Distributed systems often offer multiple services or data providers. Again, the purpose of the
service abstraction is to shield applications from the details of system implementation.
• Services are uniquely identified by name.
• Services have state and undergo state changes which may be indicated by explanatory textual
information.
• Services may provide alerts, e.g., data items worthy of special notice.
• Services may be permissioned to control access to their data.

3.2 Market Data Clients


Application developers provide non-SFC components of an application. These can be loosely referred
to as market data clients, or just clients. Clients are the consumers of the services offered by the SFC
market data models.
Clients use market data, process data and state events, and provide all the application specific
processing within an application.

3.3 Application Structure

3.3.1 Data and State Events


In general, the SFC employs an event-driven paradigm. SFC models encompass real-time data which
results in asynchronous events that must be processed by both the library and the client components.
Other events may be generated by implementation-specific components within the library.
Where fundamental to the problem domain, events are incorporated into the abstract models provided
by the SFC. There are several event generating components within the various SFC models. The
events which can be generated by a given type of component and the semantics of those events are
defined by the particular abstraction which that component represents.
As recipients of market data related events, clients must provide the interface by which events are
propagated through the application. This is accomplished by means of abstract base classes and the
use of the C++ virtual function mechanism. For each type of event generating component, there is an
abstract base class which defines the clients eligible to receive those events. These base classes
declare public virtual functions which are invoked by the event generating components. Developers of
new components create specializations of the client base classes. These specialized classes provide

SFC Developer’s Guide 12


3 THE SFC APPLICATION FRAMEWORK

application specific processing of the events generated by the SFC Libraries. An application consists
of one or more instances of various specialized client types which register with instances of market
data items to receive events relating to those items.
Clients register to receive events with individual data items (or other event generating components) in
which they have interest. The implementation of the model is responsible for managing this client
registration and for delivering the appropriate events to registered clients.

3.3.2 System Events


The SFC Library provides a large number of building blocks, or components, which can be used as the
basis for creating additional components and, ultimately, applications. Cooperation among SFC Library
components and other parts of an application is essential. In particular, it is important that components
which need access to timers and I/O do so in a “fair” manner. In general, event driven systems solve
this problem by providing a control loop which dispatches events as required.
Because the SFC components must accommodate many different kinds of application environments,
they interact with the control loop through a generic interface, an abstraction. Application designers are
free to choose whatever kind of control loop is most appropriate for their application. All that is required
by the SFC is that the designer provide a “glue” layer between the SFC interface and the control loop
implementation. The SFC makes this easier by providing a number of pre-defined glue layers for the
standard control loops provided by most GUI development environments. In addition, the SFC
provides a control loop implementation based on the select() system call. It is useful for non-GUI
applications. As an alternative, application developers can create their own implementations and glue.
The SFC abstraction for a control loop is represented by a C++ class called RTREventNotifier. This
class is described in more detail in section 4.8.3 and in the alphabetical class listing. Most of the
example applications in this manual make use of an RTREventNotifier implementation called
RTRSelectNotifier. It is an implementation (descendant) of RTREventNotifier which uses a select()
system call as the basis for a control loop. It is important to note that the components used in the
example applications will work just as well in other application contexts and with other implementations
of RTREventNotifier.
In addition to the RTRSelectNotifier, the SFC provides implementations of RTREventNotifier for X-
Window environments (RTRXtNotifier and RTRXViewNotifer) and for MS Windows
(RTRWindowsNotifier).
Use of the SFC Library does not mandate that application designers use the RTREventNotifier
interface. They may prefer to write components which interact directly with the control loop

SFC Developer’s Guide 13


3 THE SFC APPLICATION FRAMEWORK

implementation of their choice. Where portability is of concern, designers may find that they can use
the RTREventNotifier interface to their advantage.

3.4 Threading and Exceptions


SFC is not designed to work in a multi-threaded environment. Most threaded applications can be re-
written to use timers, such as the RTRTimerCmd. However if an SFC application requires thread,
make sure:
• only one thread ever accesses SFC
OR
• all uses of SFC objects should be locked with a single external lock to ensure that SFC is only
accessed by one thread at at time.
Also, SFC does not use exceptions and is not exception-aware. If an SFC application uses exceptions,
make sure that all SFC objects are cleaned up properly in the reverse order from which they were
created. Also, throwing an exception from an SFC event call-back should be avoided.

SFC Developer’s Guide 14


4 SFC MODELS
4.1 Record Subscription

4.1.1 Overview

4.1.1.1 Record Items


A record represents an item of market data as a collection of fields. Record clients are application
components which are interested in the events associated with a particular record. This interest is
expressed by the act of registering a client with a record.
The data represented by a record can be characterized by its condition. The condition of the data may
affect the way in which it is used by a client. For example, if data is suspect or stale, a display
application might indicate this by using a different color to display that data. Data condition is
expressed in the model by state variables associated with a record. Changes in the condition of the
data result in changes to record state.
Record data is represented by fields. A record is a collection of such fields, although not all records
contain the same fields. The content of a record is determined by the underlying market data. For
example, a record representing an equity instrument traded on an exchange will not contain the same
fields as a record representing the spot market for a currency. Fields are unique within a record. I.e, no
two fields in any given record will have the same identifier. Records provide both sequential (iterative)
and random (keyed) access to their constituent fields, and support queries regarding the presence of
fields within the record.
The set of field identifiers which might be found in a record is defined by the provider of that record.
The set of all field definitions used by a provider of records (a service) is contained in a database
associated with that service. In the SFC, field definitions are represented by the class
RTRFidDefinition.
Each field has a value, the semantics of which is determined by that field’s identifier. A field identifier
has two forms:
• an integer value (FID)
• a sequence of characters (name)
Associated with a given FID (or name) are, among other things, the type of field and its storage
requirements. Together, the identifier, type, and storage requirements of a field comprise a field

SFC Developer’s Guide 15


4.1 SFC MODELS

definition. The identifier also implicitly defines the semantics of the field. For example there are many
different kinds of price fields, but a BID price and an ASK price have very different semantics.
Clients may use fields in their "generic" form or interpret their contents according to their type. For
example, while a date can be represented as the string "MAR 11 1994", it may be useful to use the
numeric equivalent where day=11, month=3, year=1994. A price may be represented as the string "29
2/8" or as the floating point value 29.25. Type-specific fields are represented in the SFC for
alphanumeric, date-time, enumerated, integer, numeric, and price values. These type-specific fields
provide the capability to interpret the string value according to the rules associated with its particular
type.

4.1.1.2 Real-time Records


The value of individual fields within a record may change over time. When a record can change over
time, it is considered "real-time." Changes occur in aggregates which are known as updates or ticks.
Updates occur for a number of different reasons. They constitute distinct events which must be
conveyed to the "clients" of any given record. As with updates, record state changes are generally of
interest to clients, requiring timely propagation of these events to individual clients of the record. The
SFC class which represents real-time record items is RTRRTRecord. Real-time record clients are
represented by the class RTRRTRecordClient.
The fields which comprise real-time records also have real-time characteristics, meaning that they
change over time. Application components which are interested in the value of a field may also be
interested in updates to the field's value. Fields are responsible for notifying clients of changes in the
field's value and therefore provide mechanisms by which clients may register interest in field events.
When the field's value changes, an event is sent to each of its clients. The base type for real-time fields
in the SFC is the class RTRRTField.

4.1.1.3 Snapshot Records


Sometimes clients do not care if a record’s data updates or if its state changes. The client is only
interested in non-updating data or a "snapshot" of updating data at one point in time. In this
circumstance, record requests can be optimized and network bandwidth usage can be reduced by
using the class RTRSnapshotRecord. Snapshot record clients are represented by the class
RTRSnapshotRecordClient. The underlying data of snapshot records is never updated, so snapshot
record clients will never receive update events.
The base type for fields in a snapshot record is RTRSnapshotField. Since snapshot fields never
update, they do not accept clients.

SFC Developer’s Guide 16


4.1 SFC MODELS

4.1.1.4 Record Chains


In the IDN domain, some records are grouped together forming "chains" of records. Indexes (0#.FTSE,
0#.DJI) and most active volume lists (.AV.L, .AV.O) are two examples of where chains are used. A
record chain is an abstract model for this kind of record collection.
A record chain is a sequential list of records. Chains are considered "real-time" in nature. The list of
records may update or change in real-time. Specifically, a chain could re-sort causing a record to be
moved up, down, or out of the list. Therefore chains are implemented on top of the real-time record
model rather than the snapshot record model.
In the SFC, record chains are represented by the class RTRRecordChain. The names of individual
positions in a chain are represented by the class RTRRecordChainElement. A record chain can notify
its client when the chain has completely retrieved all of its elements. It also has events indicating errors
and state changes. A record chain element can notify its client when it updates. Clients of record
chains and record chain elements are represented by the classes RTRRecordChainClient and
RTRRecordChainElementClient, respectively.

NOTE: Record chain elements correspond to positions in a chain, not records in a chain. If the val-
ues in the third and fourth positions of a chain swap, chain element clients for the third and fourth
chain elements will each receive an update event.

4.1.1.5 Record Services


Record services are an abstraction for providers of record items. While nothing in the previous
description of records necessitates an associated service abstraction, the concept of a service is
useful in providing practical implementations of the real-time record model. A record service provides
access to records and is responsible for managing the allocation of resources (e.g., memory, I/O
bandwidth, etc.) necessary to provide the underlying data. Resource allocation is based on the priority
assigned to the record by all of the record’s clients.
Like records, record services exist in one of several states, where service state is essentially a global
condition for all data provided by that service. For example, if a service is in a stale state, all data items
provided by that service are stale. Services are responsible for notifying interested clients of changes
in their state.
A record service will always provide access to a requested record. Where a service is unable (or
unwilling) to provide data for a requested record, the record will be in an inactive state. For example,
an application may request a record which does not exist in the implementation domain (i.e., there is

SFC Developer’s Guide 17


4.1 SFC MODELS

no corresponding item of market data with the same name) or the application may not have permission
to access the underlying data. The text of an inactive record explains the reason that data will not be
provided. Once in an inactive state, a record will never transition to the active state; it is in an
unrecoverable error state. Applications should not maintain references (pointers) to inactive items.
This rule is based on practical considerations, e.g., memory management. When items are inactive,
the resources they use (memory, etc.) are eligible to be reclaimed.

4.1.1.6 Record Service Pools


Ideally, there would only be a need for one instance of a real-time record service in an application.
However, in many practical applications access to multiple services is required. Many distributed
systems provide access to several different services. These services correspond to data services
offered by different vendors or to local applications which publish data. These services may come and
go over time. Usually the decision to use a given service is made by an administrator or a user.
The RTRRTRecordService is the abstract base class for providers of real-time record data. Often
services are implemented as "proxies" for remote entities in a distributed system. For example, RTIC
based services provide access to the services available on RMDS. Services could also be
implemented to communicate directly with a datafeed, or they may be implemented locally. For
example a record service could be implemented to take page oriented data and "shred" it into records
for use within an application. An implementation of a RTRRTRecordService which is a simulator might
extract data from files. Within a given application there may be more than one implementation of the
RTRRTRecordService class. For example, RMDS-based services and a "shredder" service could
coexist within the application.
How are services created and made available to other application components? The objective is to
make as much of the application software as independent as possible of the service implementations
and particularly the creation of services.
What is required is a mechanism that allows most of the application to be independent of the details of
the service creation process. The record service pool, represented by the class
RTRRTRecordServicePool, provides the necessary level of abstraction. It represents a set containing
all available services and generates events corresponding to the "arrival" (and departure) of services.
The contents of the pool can be accessed sequentially (by iteration) or randomly (by service name).
Pool clients are represented by the class RTRRTRecordServicePoolClient.
The manner in which the pool gets populated is implementation specific. Ultimately, some part of the
application creates services and puts them in the pool. This results in an event being propagated to
interested clients from the pool. Clients may then obtain a reference to the new service.

SFC Developer’s Guide 18


4.1 SFC MODELS

4.1.1.7 Client Classes


The preceding description of record-oriented real-time data introduced several client classes (e.g.,
RTRRTRecordClient, RTRRTFieldClient, and RTRRTRecordServicePoolClient). These classes define
the abstract types for those application components which wish to process the various market data
related events generated by real-time records, services, and pools. In order to receive event
notifications, application specific classes inherit from one or more of these client classes and define
appropriate actions to be taken for each event of interest. All event generating classes in the real-time
model provide addClient() and dropClient() methods, which allow clients of the appropriate type to
register and un-register for events. Collectively, the behavior of the clients which comprise an
application defines the functionality of that application.
Record chains and record chain elements are limited to one client per object. The client classes are
RTRRecordChainClient and RTRRecordChainElementClient. Due to the one client limitation,
RTRRecordChain and RTRRecordChainElement provide setClient() and clearClient() methods for
registering and un-registering for events.

4.1.2 Design
This section provides more detail concerning the analysis and design of the real-time record model.
The purpose of this section is to show how the abstract analysis translates into specific class features.
Not all features of all classes are described. Please refer to the SFC Reference Manual for full details.

4.1.2.1 Real-time Record State


Record state is defined by the values of three record attributes: hasData, stale, and active. The four
real-time record states are defined as follows:

Record
State Description
Attributes

Active_noData hasData = False Records in this state cannot provide any fields. The
stale = True initial "image" of the record is not yet available.
active = True Records in this state may transition to any of the other
three states. Once out of this state, a record instance
will never return to it.

Table 4.1: Record States

SFC Developer’s Guide 19


4.1 SFC MODELS

Record
State Description
Attributes

Active_valid hasData = True Records in this state contain valid data. Records in this
stale = False state may transition to the Active_stale state or to the
active = True Inactive state.

Active_stale hasData = True Records in this state contain data which is may be out-
stale = True of-date, i.e. it is stale. Stale records are in a recover-
active = True able error condition and will take all necessary steps to
return to an Active_valid state.

Inactive hasData = don’t care Records transition to this state when the service which
stale = don’t care created the given record is unable or unwilling to con-
active = False tinue providing access to the underlying data item.
Once in this state, a record will never transition to
another state.

Table 4.1: Record States (Continued)

State transitions are propagated to clients as events. The events triggered by state transitions are
described as follows:
• Sync - This event indicates the availability of an initial "image". This event will only occur once for
a given record instance. The event triggers a transition to either the Active_valid state or the
Active_stale state. Record clients will receive a processRecordSync() event.
• Resync - This event indicates the availability of a subsequence "image". It also indicates a
change in state between Active_stale and Active_valid. When a resync occurs, the state of the
record must be examined. Record clients will receive a pair of events, processRecordResync()
and processResyncComplete(), to indicate data change. In case there is a change in state,
record clients will receive an additional event, processRecordStale() or
processRecordNotStale() event to indicate a state change from Active_Valid to Active_Stale or
Active_Stale to Active_Valid respectively.
• Stale - This event indicates a transition from the Active_valid state to the Active_stale state.
Record clients will receive a processRecordStale() event.
• NotStale - This event indicates a transition from the Active_stale state to the Active_valid state.
Record clients will receive a processRecordNotStale() event.

SFC Developer’s Guide 20


4.1 SFC MODELS

• Inactive - This event indicates a transition to the Inactive state. Record clients will receive a
processRecordInactive() event.
Record will also generate informational events when appropriate. Clients will receive a
processRecordInfo() event. These events never indicate a change in record state.
Records have a text() method which provides a textual explanation of the current record state. Record
clients are kept informed of progress by means of events which indicate that there is new textual data
available concerning the state of the record.
Figure 4.1 shows the various real-time record states and state transitions.

Resync
Sync
Active_noData Active_valid
Inactive Resync
Inactive Sync
Stale
NotStale

Inactive Inactive Active_stale


Resync

Active_noData (hasData = False, stale = True, active = True)


Active_valid (hasData = True, stale = False, active = True)
Active_stale (hasData = True, stale = True, active = True)
Inactive (hasData = XX, stale = XX, active = False)

Figure 4.1: Real-time Record States and Variables

SFC Developer’s Guide 21


4.1 SFC MODELS

4.1.2.2 Snapshot Record State


Note that a snapshot record only receives a Sync or Inactive event. Immediately after a snapshot
record receives a sync, the stale/valid state of the record cannot be determined. Therefore, it is always
considered stale.
Snapshot record state is defined by the values of two attributes: hasData and active. The three
snapshot record states are defined as follows:

Record
State Description
Attributes

Active_noData hasData = False Records in this state cannot provide any fields. The
stale = True initial "image" of the record is not yet available.
active = True Records in this state may transition to any of the other
three states. Once out of this state, a record instance
will never return to it.

Active_stale hasData = True Records in this state contain data which is may be out-
stale = True of-date, i.e. it is stale. Snapshots are always consid-
active = True ered stale because the data may have been updated
immediately after the snapshot was received.

Inactive hasData = don’t care Records transition to this state when the service which
stale = don’t care created the given record is unable or unwilling to con-
active = False tinue providing access to the underlying data item.
Once in this state, a record will never transition to
another state.

Table 4.2: Snapshot Record States

State transitions are propagated to clients as events. Snapshot can only receive two event:
• Sync - This event indicates the availability of an initial "image". This event will only occur once for
a given record instance. The event triggers a transition to the Active_stale state. Record clients
will receive a processRecordSync() event.

SFC Developer’s Guide 22


4.1 SFC MODELS

• Inactive - This event indicates a transition to the Inactive state. Record clients will receive a
processRecordInactive() event. Snapshot clients receive this event if the record does not exist
or if the record object is deleted.
Figure 4.2 shows the various snapshot record states and state transitions.

Active_noData
Sync

Inactive Active_stale

Inactive
Inactive

Active_noData (hasData = False, stale = True, active = True)


Active_stale (hasData = True, stale = True, active = True)
Inactive (hasData = XX, stale = XX, active = False)

Figure 4.2: Snapshot Record States and Variables

SFC Developer’s Guide 23


4.1 SFC MODELS

4.1.2.3 Record Chain State


Record chain state is defined by four attributes: isValid, complete, stale, and error. The five record
chain states are defined as follows:

Record
State Description
Attributes

notComplete isValid = don’t care The chain has been requested. Nothing else is
complete = False know about its validity or state yet.
stale = don’t care
error = False

Complete_stale isValid = True The chain is valid and complete, but one of the
complete = True chain headers is currently stale.
stale = True
error = False

Complete_notStale isValid = True The chain is valid, complete, and ready to be used.
complete = True
stale = False
error = False

Error isValid = don’t care Some error occurred when processing one of the
complete = don’t care chain headers. This state could occur before a
stale = don’t care chain is complete if the last valid chain header
error = True points to a record that does not exist (e.g. if the
NEXT_LR field of 1#.AV.O were set to 2#.AV.O, a
non-existent RIC, the chain would go into the error
state). This state could also occur after the chain is
complete if any of the records that constitute chain
headers become inactive for any reason.

Invalid isValid = False The RIC used for the chain name is a valid RIC, but
complete = False it is not a chain header. Maybe the application
stale = don’t care should re-request the RIC as a regular record.
error = False

Table 4.3: Record Chain States

SFC Developer’s Guide 24


4.1 SFC MODELS

State transitions are propagated to clients as events. Events that trigger state transitions are described
as follows:
• Complete - This event indicates that all of the values currently available for the chain have been
completely received. This event will only occur once for a given chain instance. The event triggers
a transition from the notComplete state to either the Complete_stale or Complete_notStale state.
The chain client will receive a processChainComplete() event.
• Error - This event indicates that some error occurred while processing one of the chain headers
(e.g. 1#.DJI). The chain client will receive a processChainError() event. This event will only
occur once for a given chain instance. If the chain’s count() is greater than zero, the current
contents of the chain can still be used. If the client continues to use the chain, it should check to
see if the chain resized.
• Stale - This event indicates a transition from the Complete_notStale state to the Complete_stale
state. The chain client will receive a processChainStale() event.
• NotStale - This event indicates a transition from the Complete_stale state to the
Complete_notStale state. The chain client will receive a processChainNotStale() event.
• Invalid - This event indicates a transition to the Invalid state. This event will occur if the requested
chain is a valid record, but it does not include all of the required fields. The chain client will receive
a processRecordInactive() event. This event will only occur once for a given chain instance.
A record chain is complete when its elements can be completely constructed. A record chain is invalid
when the provided name is an available record, but that record is not a chain (e.g. IBM.N is requested
as a chain). A record chain is in the error state if it could not be completely constructed or if one of its
internal records (records that define the chain, not the chain elements’ records) becomes inactive. For
example, if 1#.DJI were to become inactive, the chain client would receive a processChainError()
event.
Chain client can receive additional events to indicate that the contents of the chain have changed.
• Partial - This event indicates that some elements have been added to the chain, but the chain is
not yet complete. The chain client will receive a processChainPartial() event..This event is only
received when the chain is in the notComplete state. It can be used by applications to proactively
request records listed in a chain before the chain is complete.
• Resize - This event indicates that elements have been added to or removed from the chain. The
chain client will receive a processChainResize() event. This event is only received when the
chain is in the Complete_stale or Complete_notStale state. When this event is received, the chain

SFC Developer’s Guide 25


4.1 SFC MODELS

client should also check to see if the chain moved between the Complete_stale and
Complete_notStale states.

NOTE: Record chain elements are always added to and removed from the end of the chain. For
example, if a value Y’ is inserted before the last value ’Z’ in the chain, the last chain element’s client
will receive a ChainElementUpdate event for a change from ’Z’ to ’Y’. Then the chain client will
receive a Resize event for 1 additional element. This element will contain the value ’Z’.

• UpdateComplete - This event indicates that a number of chain elements have changed but the
change did not resize. The chain client will receive a processChainUpdateComplete() event.
This event is only received when the chain is in the Complete_stale or Complete_notStale state.
When this event is received, the chain client should also check to see if the chain moved between
the Complete_stale and Complete_notStale states.
Figure 4.3 shows record chain states and events causing state transitions.

SFC Developer’s Guide 26


4.1 SFC MODELS

Invalid
notComplete Invalid

Error
Complete Complete

Error
Error Error

Stale
Complete_stale Complete_notStale
NotStale

notComplete (isValid = XX, complete = False, stale = XX, error = False)


Complete_stale (isValid = True, complete = True, stale = True, error = False)
Compete_notStale (isValid = True, complete = True, stale = False, error = False)
Error (isValid = XX, complete = XX, stale = XX, error = True)
Invalid (isValid = False, complete = False, stale = XX, error = False)

Figure 4.3: Record Chain States and Variables

SFC Developer’s Guide 27


4.1 SFC MODELS

4.1.2.4 Service State


The state of services is determined by the value of two attributes: stale and active. The three services
states are defined as follows:

Record
State Description
Attributes

Stale stale = True The service is not available on the network. This state
active = True could be because the initial connection between the
SFC application and the infrastructure has not been
established, information from this service has not been
retrieved from the infrastructure, or the service is sim-
ply not available. Stale is a recoverable condition.
Items may be requested from stale services, but they
will remain stale until the service itself is no longer
stale and can automatically request the items.

Ok stale = False The service has been found in the market data infra-
active = True structure and is ready to handle item requests.

Inactive stale = don’t care This state should never occur for services on a net-
active = False work because the application can never know if the
service will recover sometime in the future. Services
representing local publishers could go into this state
because the application has control over the state of
the local publisher. Services also go into this state
right before their objects are destroyed.

Table 4.4: Service States

State transitions are propagated to clients as events. The events triggered by state transitions are
described as follows:
• Sync - This event indicates the service has been found and is ready to accept requests. Unlike
the record sync event, this event can occur multiple times for a given service instance. However,
it will never occur twice in a row. This event triggers a transition from the Stale state to the Ok
state. Service clients will receive a processServiceSync() event.

SFC Developer’s Guide 28


4.1 SFC MODELS

• Stale - This event indicates a transition from the Ok state to the Stale state. Service clients will
receive a processServiceStale() event.
• Inactive - This event indicates a transition to the Inactive state. Service clients will receive a
processServiceInactive() event and should release all references to the service.
Services will also generate informational events when appropriate. Clients will receive a
processServiceInfo() event. These events never indicate a change in the service’s state. Services
have a text() method which provides a textual explanation of the current state of the service.
Figure 4.4 shows the various service states and state transitions.

Stale Sync

Stale
Inactive Ok

Inactive
Inactive

Stale (stale = True, active = True)


Ok (stale = False, active = True)
Inactive (stale = XX, active = False)

Figure 4.4: Service States and Variables

4.1.2.5 Record Client Management


Records may have multiple clients, and those clients may be registered with multiple record items. In
other words, there is n to n cardinality between record items and clients.
As an example, suppose an application needs the capability to display one or more individual records
and also must provide limit minding capability. One possible solution entails designing two new client

SFC Developer’s Guide 29


4.1 SFC MODELS

classes, i.e., specialized descendants of RTRRTRecordClient. The first, a "quote display" client is
designed to display a single record. The second, a "limit minder" client, is designed to display the trade
prices of one or more records. At run-time the application will consist of one or more quote display
clients and a limit minding client. Figure 4.5 illustrates the run-time relationships which result when the
application is displaying two records ("IBM.N" and "DEM=") and also performing limit minding on the
same records. In this case, there are two record instances and three client instances, two of type
"Quote Display" and one of type "Limit Minder". Each record has two clients, one each of type Quote
Display and type Limit Minder. The single instance of Limit Minder is a client of two records; the
instances of Quote Display are each clients of a single record.

Quote Display Client


RTRRTRecord
viewing "IBM.N" "IBM.N"

Client Limit Minder Client


Instances Record
minding "IBM.N" & "DEM=" Instances
RTRRTRecord
"DEM="
Quote Display Client
viewing "DEM="

Figure 4.5: Record and Client Run-time Relationships Example

In a typical application, these relationships are defined dynamically, i.e., on the basis of user input or
other events, meaning that clients may be dynamically added (allocated) or removed (deleted) at any
time.
The RTRRTRecord class defines three methods for "client management". They are:
void addClient(RTRRTRecordClient&)
This method registers a client with an individual record so that the given client will receive all
events subsequently generated by that record.

SFC Developer’s Guide 30


4.1 SFC MODELS

void dropClient(RTRRTRecordClient&)
This method un-registers a client with a particular record so that the given client will no longer
receive events from that record.
RTRBOOL hasClient(RTRRTRecordClient&)
This method is used to determine whether a given client is currently registered to receive events
from a particular record.

4.1.2.6 Record Clients


Record clients are descendants of (inherit from) RTRRTRecordClient. As such, they can register to
receive events from one or more instances of RTRRTRecord. Once registered with a record they will
receive all events generated by that record instance. Events are propagated by means of class
member functions; i.e., when a record needs to "generate an event", it will invoke the appropriate
member function of each client currently registered.
The "sync" event is one example of an event which can be generated by a record. The corresponding
member function of RTRRTRecordClient is processRecordSync(RTRRTRecord&). Thus, when a
record transitions from the Active_noData state to, say, the Active_valid state, it will invoke the
processRecordSync() member function of each registered client.
Referring to the example illustrated in Figure 4.5, if the IBM.N record instance generates a sync event,
it must invoke the appropriate method for each of it clients, of which there are two—one each of type
QuoteDisplay and type LimitMinder. In this case, each method does something different; one draws a
display, the other initializes limit minding.
All events which can be generated by instances of RTRRTRecord have a corresponding processing
method in RTRRTRecordClient. In some cases, a default implementation (behavior) has been defined.
In C++ terms, those event processing methods with default behavior are declared as virtual functions.
Those for which there is no default behavior are declared as pure virtual. The event processing
methods of RTRRTRecordClient for which there is no default (declared pure virtual) are as follows:
virtual void processRecordInfo(RTRRTRecord&) = 0
This event indicates that new informational text concerning the given record is available via the
records text() method.
virtual void processRecordSync(RTRRTRecord&) = 0
The given record has made the transition out of the Active_noData state. The client can process
field data as appropriate according to the condition of the data (stale vs. not stale).

SFC Developer’s Guide 31


4.1 SFC MODELS

virtual void processRecordStale(RTRRTRecord&) = 0


The data for the given record is now in a stale condition.
virtual void processRecordNotStale(RTRRTRecord&) = 0
The data for given record is no longer in a stale condition.
virtual void processRecordInactive(RTRRTRecord&) = 0
The given record is no longer active. This represents an unrecoverable error condition. The client
should un-register from the record (using dropClient()) and ensure that no further references are
made to that record or to any of that records fields. The text() method provides informational text
indicating the reason for this event.
The event processing methods of RTRRTRecordClient for which there is a default implementation
(declared virtual) are as follows:
virtual void processCloseTick(RTRRTRecord&)
This update event indicates that the fields modified by this update are not changing as a result of
market activity but rather as a reflection of changes in certain historical fields. For example, a field
which reflects the closing price for the previous day’s trading will be updated by a close tick prior
to a new day of trading. This event is generated by a record instance prior to updating individual
fields which are affected by this tick. The default implementation invokes the processUpdate()
method of this client.
virtual void processCorrectionTick(RTRRTRecord&)
This update reflects corrections to previously delivered data which is in error. Updates of this type
do not indicate market activity. This event is generated by a record instance prior to updating
individual fields which are affected by this tick. The default implementation invokes the
processUpdate() method of this client.
virtual void processRecordResync(RTRRTRecord&)
This update reflects the recovery from a recoverable error condition. It does not reflect market
activity. This event is generated by a record instance prior to updating individual fields which are
affected by the recovery. The default implementation invokes the processUpdate() method of this
client.
virtual void processUpdate(RTRRTRecord&)
This is the generic update event which is invoked as the default processing by the above event
processing methods. Clients who wish to pre-process update events but who do not need to
differentiate among updates by their semantics can redefine just this event processing method.

SFC Developer’s Guide 32


4.1 SFC MODELS

Again, this "event" occurs prior to the individual field update events. The default implementation
does nothing, i.e., pre-update events are ignored.
virtual void processUpdateComplete(RTRRTRecord&)
This event is generated by a record after all fields affected by a tick have been modified. Clients
who wish to post-process an update event can redefine this method. The default implementation
does nothing, i.e., post-update events are ignored.
virtual void processResyncComplete(RTRRTRecord&)
This event is generated by a record after all fields affected by a tick have been modified. Clients
who wish to post-process a re-sync event can redefine this method. The default implementation
invokes processUpdateComplete().

4.1.2.7 Access to Fields


Records must provide both random and sequential access to their constituent fields. Sequential
access is provided by means of an "iterator" class, an instance of which is associated with a particular
record instance and provides access to each field of the record in turn. The basic record iterator is
defined by the class RTRRTRecordIterator.
A record iterator instance is obtained using the iterator() method of class RTRRTRecord. Figure 4.6
shows how a record iterator is used to traverse all the fields of a record. The start() method is invoked
to initiate a new traversal. This method makes the first field of the record available for inspection via
the field() method of the iterator. The returned reference is of type RTRRTField, which, in this case, is
the "display name". Invoking the forth() function makes available the next field, in this case "trade
price 1", and so-on. After the call to start() and after each call to forth(), the off() condition should be
tested. When off() returns RTRTRUE, the iteration has been completed.

SFC Developer’s Guide 33


4.1 SFC MODELS

Display Trade Trade High 1 Low 1 Bid


Name Price 1 Price 2

forth() forth() forth() forth() forth() forth()

off() start() off()

Figure 4.6: Accessing All Fields Using a Record Iterator

4.1.2.8 Field Updates


The SFC provides two techniques for obtaining updated field values. Sequential access to updated
fields can be achieved by use of a class which is a variant on the iterator class described in the
previous section. An instance of RTRRTRecordUpdateIterator is only valid during the
processUpdateComplete() event and provides access to only those fields which have updated as a
result of the current event. This is illustrated in Figure 4.7.

Display Trade Trade High 1 Low 1 Bid


Name Price 1 Price 2

forth() forth() forth()

off() start() off()

Figure 4.7: Accessing Updated Fields Using a Record Update Iterator

SFC Developer’s Guide 34


4.1 SFC MODELS

An alternative technique is to define a class which is a descendant of RTRRTFieldClient and which


can then be registered with one or more fields of interest. Field update events are generated by fields
between the pre and post update events generated by the record which contains those fields.
Figure 4.8 illustrates the event sequence which will occur (assuming that the default processing for
processTick() is retained) when a record called "DEM=" updates the "BID" and "ASK" fields.

RTRRTField ("BID")
RTRRTField ("ASK")
RTRRTRecordClient RTRRTFieldClient
RTRRecord (DEM=)
processTick()

processUpdate()
processFieldUpdate()

processFieldUpdate()

processUpdateComplete()

Figure 4.8: Record and Field Update Event Sequence

4.1.3 Implementation
Currently, the SFC provides two implementations of the real-time and snapshot record models. While
most application components should refer only to the base classes mentioned in the preceding
section, the "main" routine or initialization section of an application must instantiate one or more
implementation specific classes.
SFC includes implementation classes for use by both single (simple) and multiple service (more
complex) applications. These classes encapsulate the procedures for creating an SSL connection and
the record services which use that connection. They are:

SFC Developer’s Guide 35


4.1 SFC MODELS

• RTRSSLRTRecordService - This class is a descendant of RTRRTRecordService that creates its


own SSL session. It is typically used by simple applications which require access to only a single
service. Readers familiar with SSL functionality will realize that SSL record data is delivered in the
Marketfeed format. All decoding and interpretation of SSL messages is handled by the
implementation classes, a complete description of which is beyond the scope of this manual.
• RTRTIBRTRecordService - This class is a descendant of RTRRTRecordService that creates its
own TIB session. It is typically used by simple applications which require access to only a single
service. It can be used to consume data from an RTIC.
A typical application will instantiate one of the implementation service classes in main() (or its
equivalent).

4.1.3.1 Multiple Services


Some applications use more than one service. The connection and service pool factory classes make
it easy to incorporate multiple services in a single application.
RTRSSLConnection and RTRTIBConnection can be used to fine tune the connection parameters for
the implementation record services. They are described in detail in section 4.8.1.
RTRSSLServicePoolFactory and RTRTIBServicePoolFactory can be used to manage the life-cycle of
and share a single connection among several market data services. They are described in detail in
section 4.8.2.

4.1.4 Class Summaries


This section provides a summary of the classes which comprise the models for record data. The table
matches snapshot record classes with their real-time record counterparts. For more details please
refer to the appropriate sections of the alphabetical class reference.

Real-time Snapshot

RTRRTRecord RTRSnapshotRecord

RTRRTRecordClient RTRSnapshotRecordClient

RTRRTRecordIterator RTRSnapshotRecordIterator

Table 4.5: Real-time Record Classes vs. Snapshot Record Classes

SFC Developer’s Guide 36


4.1 SFC MODELS

Real-time Snapshot

RTRRTRecordUpdateIterator not applicable

RTRRTField RTRSnapshotField

RTRRTAlphanumericField, etc. RTRSnapshotAlphanumericField, etc.

RTRRTFieldClient not applicable

RTRRTRecordService RTRSnapshotRecordService, or just use


RTRRTRecordService

RTRRTRecordServicePool use RTRRTRecordServicePool

RTRRTRecordServicePoolClient use RTRRTRecordServicePoolClient

Table 4.5: Real-time Record Classes vs. Snapshot Record Classes (Continued)

4.1.4.1 Real-time Record Class Summary


• RTRRTRecord - This class defines an item of real-time record data. Records provide both linear
and sequential access to their constituent fields. Records have state which may change over
time. Data and state change events are propagated to other application components which have
registered with a record for the purpose of receiving record events. Records support multiple
clients.
• RTRRTRecordClient - This is the abstract base class for application components which wish to
register with one or more real-time records in order to receive data and state events from those
records.
• RTRRTRecordIterator - Instances of this class provide sequential access to all the constituent
fields within a given record.
• RTRRTRecordUpdateIterator - Instances of this class are used during update events to provide
sequential access to those fields within a real-time record which where modified by the current
update.
• RTRRTField - This class defines the base type for the constituent parts of a record. Fields are
identified by name or FID, have a specific type, and provide various forms of access to the
underlying data which they represent.

SFC Developer’s Guide 37


4.1 SFC MODELS

• RTRRTAlphanumericField, RTRRTDateField, RTRRTEnumeratedField, RTRRTIntegerField,


RTRRTPriceField - These descendants of RTRRTField provide type-specific interpretation of the
underlying data.
• RTRRTFieldClient - This is the abstract base class for application components which wish to
register with one or more individual fields in order to receive data and state events from those
fields.
• RTRRTRecordService - This class provides access to real-time record data and manages the
aggregate state of those records. Service state change events are propagated to those
application components which register to receive those events.
• RTRRTRecordServicePool - Instances of this class serve as a repository for all available real-
time record services. Typically there is only one instance of this type within an application. A pool
provides random and sequential access to the services it contains. A pool provides the means to
insert and remove services and allows clients to register for the change events which are
generated when the contents are modified.
• RTRRTRecordServicePoolClient - This is the abstract base class for components which wish to
register with one or more real-time record service pools in order to receive data and state events
from those pools.

4.1.4.2 Snapshot Record Class Summary


• RTRSnapshotRecord - This class defines an item of snapshot record data. Records provide
both linear and sequential access to their constituent fields. Snapshot records do not change
state or update data. Snapshot records support multiple clients.
• RTRSnapshotRecordClient - This is the abstract base class for application components which
wish to register with one or more snapshot records in order to receive data for those records.
• RTRSnapshotRecordIterator - Instances of this class provide sequential access to all the
constituent fields within a given snapshot record.
• RTRSnapshotField - This class defines the base type for the constituent parts of a record. Fields
are identified by name or FID, have a specific type, and provide various forms of access to the
underlying data which they represent. Snapshot fields do not update, so they do not have clients.
• RTRSnapshotAlphanumericField, RTRSnapshotDateTimeField,
RTRSnapshotEnumeratedField, RTRSnapshotIntegerField, RTRSnapshotPriceField -

SFC Developer’s Guide 38


4.1 SFC MODELS

These descendants of RTRSnapshotField provide type-specific interpretation of the underlying


data.
• RTRSnapshotRecordService - This class provides access to snapshot record data.

4.1.4.3 Record Chain Class Summary


• RTRRecordChain - This class defines a chain of real-time records. Status, error, and state
change events are propagated to the client of the chain. Record chains support only one client.
• RTRRecordChainClient - This is the abstract base class for application components which wish
to register with one or more record chains to receive events from those chains.
• RTRRecordChainIteratorPtr - Instances of this class provide sequential access to all the
constituent elements in a given record chain. This iterator is reference counted, meaning clients
should always request an iterator from the chain. The iterator will be deleted automatically when it
is no longer referenced by any variables.
• RTRRecordChainElement - This class encapsulates the name of a record in a record chain. If it
updates, it propagates the event to its client. Record chain elements support only one client.
• RTRRecordChainElementClient - This is the abstract base class for application components
which wish to register with one or more record chain elements to receive update events from
those elements.

4.1.4.4 Summary of Other Classes in the Record Cluster


• RTRMDServiceClient - This is the abstract base class for components which wish to register
with one or more instances of record or page services in order to receive data and state events
from those services.
• RTRFidDb - This class represents the database of field definitions used by a particular service.
• RTRFidDefinition - This class represents the definition for an individual field. A definition
comprises the identification (name and FID) of a field and the type. The type determines the way
in which the raw data should be interpreted; the identity defines the meaning of the field.

SFC Developer’s Guide 39


4.1 SFC MODELS

4.1.5 Examples
SFC includes several examples which highlight different parts of the record model. All of these
examples can be found the sfc/examples/realtime/ directory, with the exception of Quote, which is
only available for Windows. The rest of the examples are very similar. They typically have two parts:
1. main() function that:
• parses command line arguments
• creates a service pool factory or record service
• requests a record, field or chain
• creates the appropriate SFC client and registers it with the market data item
• creates the event control loop
2. SFC client implementation that is responsible for
• processing data and status events
• printing output to standard out
The following table summarized the record examples and details where more information about them
can be found.

Example Description Refer to...

RecSnap Snapshot client recsnapclient.*


• creates a RTRSnapshotRecordClient recsnap.C
• outputs the record image received section 4.1.6

RecUpd Record client recupdclient.*


• creates a RTRRTRecordClient recupd.C
• outputs the record image and updates received section 4.1.7

RecFld Field client tickclient.*


• creates a RTRRTRecordClient and RTRRTFieldClient recfld.C
• outputs the record’s BID, ASK, and TRDPRC_1 on section 4.1.8
image
• uses field client to determine if TRDPRC_1 has changed
on update

Table 4.6: Record Examples

SFC Developer’s Guide 40


4.1 SFC MODELS

Example Description Refer to...

RecTick Multiple record clients tickclient.*


• creates one or more RTRRTRecordClients rectick.C

Ticker Configured record and pool client tickclient.*


• uses a config file tickmon.*
• creates a service pool factory ticker.C
• access a service from the factory ticker.config
• creates one or more RTRRTRecordClients section 4.1.9

ChainUpd Chain Client Chain*Client.*


• creates a RTRRecordChainClient chainupd.C
• creates RTRRecordChainElementClients for the chain section 4.1.10
• adds, removes and changes chain element clients as
needed

Quote • provides simultaneous access to RMDS and Triarch mfcquote.pdf


(win32 only) through multiple service pool factories (win32 only)
• provides a unified service list through pool clients
• creates record, chain, and field clients
• displays chains and records in a window using display
templates.

Table 4.6: Record Examples (Continued)

4.1.6 Record Snapshot Client


The RecSnap example defines a simple record client component, RecordSnapshotClient. The
purpose of this class is to print a snapshot of a record image on the standard output device. This
record client is not concerned with updates or any other events once the initial image has been
extracted.
In order to receive data in a record event, RecordSnapshotClient must be a descendant of
RTRSnapshotRecordClient and therefore must provide implementations of all pure virtual methods
inherited from its ancestor. These methods correspond to the events which can be received from
RTRSnapshotRecord, and their implementation defines the behavior of this class. If the client were not
interested in some of the events, the event processing methods would be implemented to do nothing.

SFC Developer’s Guide 41


4.1 SFC MODELS

This class processes the following events:


• SnapshotInfo
• SnapshotSync
• SnapshotInactive

4.1.6.1 Declaration of RecordSnapshotClient


The following code is taken from recsnapclient.h and shows the declaration for
RecordSnapshotClient:
#ifndef _recsnapclient_h
#define _recsnapclient_h

#include "rtr/snaprec.h" // Defines RTRSnapshotRecordClient


class RTRSnapshotRecordService; // Forward declaration

class RecordSnapshotClient :
public RTRSnapshotRecordClient
{
public:
// Constructor
RecordSnapshotClient(RTRSnapshotRecordService& service, const char *symbol);

// Destructor
~RecordSnapshotClient();

// Event processing - from RTRSnapshotRecordClient


void processSnapshotInfo(RTRSnpahotRecord&);
// This method invoked when there is new text associated with the
// record. No state change is implied.

void processSnapshotSync(RTRSnapshotRecord&);
// This method invoked when there is an initial image for the
// record. (It can only happen once.)

void processSnapshotInactive(RTRSnapshotRecord&);
// This method invoked when the record has made the transition to
// the inactive state.

SFC Developer’s Guide 42


4.1 SFC MODELS

protected:
// Implementation attributes
RTRSnapshotRecord *_record;

};
#endif

4.1.6.2 Definition of RecordSnapshotClient


The constructor of this class illustrates the correct procedure for accessing records from a service. In
pseudo-code the procedure is as follows:
Get record reference
Add client to record
If record active then
If record has data then
process data and data condition
else
clean up
Notice that the processSnapshotSync() method uses an iterator to access all the fields in the record.
The proper cleanup technique is illustrated in several places:
• in the destructor, in case the client is deleted while still a client of the record;
• in processSnapshotSync(), after the client is finished with the record; and
• in processSnapshotInactive(), after the client is informed of an unrecoverable error.
The following code contains the implementation of RecordSnapshotClient. Comments which are
numbers (e.g., // 1) refer to more extensive comments at the end of the source file.

#include "rtr/rtrnotif.h"// Access to event loop


#include "rtr/snaprecsrv.h"// RTRSnapshotRecordService

#include "recsnapclient.h"

// Constructor
RecordSnapshotClient::RecordSnapshotClient(
RTRSnapshotRecordService& service, const char *symbol)
: _record(0)
{

SFC Developer’s Guide 43


4.1 SFC MODELS

// 1
_record = &(service.snapshotRecord(symbol));
_record->addClient(*this);
if ( _record->active() )
{
if ( _record->hasData() )
processSnapshotSync(*_record);
else
processSnapshotInfo(*_record);
}
else
{
// 2
cout << symbol << " - Inactive: " << _record->text() << endl;
_record->dropClient(*this);
_record = 0;
}
}

// Destructor
RecordSnapshotClient::~RecordSnapshotClient()
{
// 3
if ( _record )
_record->dropClient(*this);
}

// Event processing methods

void RecordSnapshotClient::processSnapshotInfo(RTRSnapshotRecord& record)


{
// 4
cout << record.symbol() << " - Info : " << record.text() << endl;
}

void RecordSnapshotClient::processSnapshotSync(RTRSnapshotRecord& record)


{
// 5
// Access each field from the record using an iterator

SFC Developer’s Guide 44


4.1 SFC MODELS

// 6
RTRSnapshotRecordIterator iterator = record.iterator();
for (iterator.start(); !iterator.off(); iterator.forth())
{
// Print the name and value of each field
RTRSnapshotField& field = iterator.field();
cout << field.name() << " " << field.string() << endl;
}
// Clean up and terminate the application
// 7
record.dropClient(*this);
_record = 0;
RTREventNotifierInit::notifier->disable();
}

void RecordSnapshotClient::processSnapshotInactive(RTRSnapshotRecord& record)


{
cout << record.symbol() << " - Inactive : " << record.text() << endl;
record.dropClient(*this);
_record = 0;
RTREventNotifierInit::notifier->disable();
}

// 1 Records should always be accessed in this manner


// * Obtain a reference to the desired record
// * Register a client with the record
// * Test the state of the record
// Services return references to records, meaning that they are never
// null. However, because clients should not retain references to inactive
// records, this class stores a pointer to the record. This so that the
// pointer can be set to null in the event of the record being inactive.
//
// 2 Clients should never remain registered with records in the inactive state
//
// 3 Be sure to un-register clients when clients are destructed
//
// 4 Records provide informational text about their state.
//
// 5 The record "sync" event occurs when a record transitions to the
// "hasData" state. This transition/event only occurs once for a given

SFC Developer’s Guide 45


4.1 SFC MODELS

// record.
//
// 6 Records provide both sequential and "random" access to their constituent
// fields.
//
// 7 This client terminates the application once the record sync event
// is received. This is not typical behaviour for record clients.

4.1.6.3 RecSnap Application


This class by itself does not comprise an application. A complete application must provide access to
an implementation of RTRRTRecordService and must instantiate one (or more) instance of
RecordSnapshotClient. The next section illustrates such an application.
This application (recsnap.C) uses the RTRSelectNotifier for the control loop and combines an SSL or
TIB implementation of RTRRTRecordService with an instance of RecordSnapshotClient. The control
loop is defined by the SFC application framework introduced in Chapter 3 and presented in more detail
in section 4.8.3 and in the SFC Reference Manual.

// Some of the code has been omitted for brevity.


// See sfc/examples/realtime/recsnap.C for all of the code

#include "recsnapclient.h"
#include "rtr/selectni.h"// RTRSelectNotifier
#include "rtr/tibrtsvc.h"
#include "rtr/sslrtrs.h"

RTRCmdLine RTRCmdLine::cmdLine;

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


{
RTRString serviceName, infra, symbol;
RTRString servicePort, network, daemon;

// Read command line parameters, set serviceName, infra, and symbol.


// For TIB, also set servicePort, network, and daemon.
// ...

RTRRTRecordService *service = 0;

SFC Developer’s Guide 46


4.1 SFC MODELS

// Select which architecture to consume from


if (infra == "tib")
{
service = new RTRTIBRTRecordServiceService(appId, serviceName,
servicePort, network, daemon);
}
else if (infra == "ssl")
{
service = new RTRSSLRTRecordService(appId, serviceName);
}
else
{
cout << "invalid infrastructure: " << infra << endl;
return -1;
}

if ( !service->active() )
{
cerr << "Service error: " << service->text() << endl;
delete (service);
return -1;
}

RecordSnaphotClient client(*service, symbol);


RTRSelectNotifier::run();

delete service;
return 0;
}

4.1.7 Real-time Record Client


The RecUpd example is similar to RecSnap, but it adds functionality to monitor updates from the
record of interest. To receive update and state change events this class uses the real-time record
classes. It uses a RTRRTRecordService to get a RTRRTRecord. RecordUpdateClient is a subclass of
RTRRTRecordClient, so it will receive RecordSync, RecordInfo, and RecordInactive events instead of
SnapshotSync, SnapshotInfo, and SnapshotInactive events. Since the record will be monitored
continuously, this class also provides processing for stale events and recovery.
RecordUpdateClient processes these events by overriding virtual methods from RTRRTRecordClient::

SFC Developer’s Guide 47


4.1 SFC MODELS

• RecordSync
• RecordInfo
• RecordInactive
• RecordStale
• RecordNotStale
RecordUpdateClient also processes this event by overriding the default behavior (which does nothing):
• UpdateComplete

4.1.7.1 Declaration of RecordUpdateClient


The declaration of RecordUpdateClient illustrates the basic techniques for processing record update
events. This class is designed to print the image of the requested record and then monitor that record
for updates. The values of updated fields are printed.
This class is similar to RecordSnapshotClient but provides processing for the RecordStale/
RecordNotStale events and overrides the default event processing for UpdateComplete events.

#ifndef _recupdclient_h
#define _recupdclient_h
#include "rtr/rtrec.h"// Defines RTRRTRecordClient

class RecordUpdateClient :
public RTRRTRecordClient
{
public:
// Constructor
RecordUpdateClient(RTRRTRecordService& srvc, const char *symbol);

// Destructor
~RecordUpdateClient();

// Event processing - from RTRRTRecordClient


void processRecordInfo(RTRRTRecord&);
// This method invoked when there is new text associated with the
// record. No state change is implied.

SFC Developer’s Guide 48


4.1 SFC MODELS

void processRecordSync(RTRRTRecord&);
// This method invoked when there is an initial image for the
// record. (It can only happen once.)

void processRecordStale(RTRRTRecord&);
// This method invoked when the record has made the transition to
// the stale state.

void processRecordNotStale(RTRRTRecord&);
// This method invoked when the record has made the transition out
// of the stale state.

void processRecordInactive(RTRRTRecord&);
// This method invoked when the record has made the transition to
// the inactive state.

void processUpdateComplete(RTRRTRecord&);
// This method invoked when the record has completed a update.

protected:
// Implementation attributes
RTRRTRecord *_record;

};
#endif

4.1.7.2 Definition of RecordUpdateClient


The definition of RecordUpdateClient does most of the event processing work. The procedure used in
the constructor follows the pattern:
Add a new client to the record
If the record is active then
If the record has an initial image then
process that image and the current condition of the data
else
process the informational text and wait for record events
else
process the inactive record state

SFC Developer’s Guide 49


4.1 SFC MODELS

This procedure should be used in all record client classes. It is especially important that clients do not
assume that they are the "first" or only client to access a given record. This is because the record may,
for example, already be in the "hasData" state, in which case it will never again generate the Sync
event. In general it should be assumed that a record instance may already be in use by some other
client within the application.
Note that while the processRecordSync() and processRecordNotStale() methods use an instance
of RTRRTRecordIterator to access all fields in the record, the processUpdateComplete() method
uses an instance of RTRRTRecordUpdateIterator which provides access to only those fields which
have been updated by the most recent update event.
//
// This file contains the implementation of RecordUpdateClient
//

#include "rtr/rtrnotif.h"// Access to event loop


#include "rtr/rtrecsrv.h"// RTRRTRecordService

#include "recupdclient.h"

// 1
RecordUpdateClient::RecordUpdateClient(
RTRRTRecordService& service, const char *symbol)
: _record(0)
{
// Obtain a record reference, register with the record and check
// its state.
_record = &(service.rtRecord(symbol));
_record->addClient(*this);
if ( _record->active() )
{
if ( _record->hasData() )
processRecordSync(*_record);
else
processRecordInfo(*_record);
}
else
{
cout << symbol << " - Inactive: " << _record->text() << endl;
_record->dropClient(*this);

SFC Developer’s Guide 50


4.1 SFC MODELS

_record = 0;
}
}

RecordUpdateClient::~RecordUpdateClient()
{
if ( _record )
_record->dropClient(*this);
}

void RecordUpdateClient::processRecordInfo(RTRRTRecord& record)


{
cout << record.symbol() << " - Info : " << record.text() << endl;
}

void RecordUpdateClient::processRecordSync(RTRRTRecord& record)


{
// Display the record image.
RTRRTRecordIterator iterator = record.iterator();
for (iterator.start(); !iterator.off(); iterator.forth())
{
RTRRTField& field = iterator.field();
cout << field.name() << " " << field.string() << endl;
}
}

void RecordUpdateClient::processRecordStale(RTRRTRecord& record)


{
// Print the textual information regarding the records stale state
cout << record.symbol() << " - Stale : " << record.text() << endl;
}

void RecordUpdateClient::processRecordNotStale(RTRRTRecord& record)


{
// Redisplay the updated image.
RTRRTRecordIterator iterator = record.iterator();
for (iterator.start(); !iterator.off(); iterator.forth())
{
RTRRTField& field = iterator.field();
cout << field.name() << " " << field.string() << endl;

SFC Developer’s Guide 51


4.1 SFC MODELS

}
}

void RecordUpdateClient::processRecordInactive(RTRRTRecord& record)


{
cerr << record.symbol() << " - Inactive : " << record.text() << endl;
record.dropClient(*this);
_record = 0;
RTREventNotifierInit::notifier->disable();
}

void RecordUpdateClient::processUpdateComplete(RTRRTRecord& record)


{
// Display the updated fields from the current record update
// 2
RTRRTRecordUpdateIterator iterator = record.updateIterator();
cout << endl;
for (iterator.start(); !iterator.off(); iterator.forth())
{
RTRRTField& field = iterator.field();
cout << field.name() << " " << field.string() << endl;
}
}

// 1 It is assumed that the reader is familiar with the implementation


// of RecordSnapshotClient
//
// 2 The update iterator is similar to the "image" iterator, however it
// only traverses fields which were updated during the current tick.
// It is only valid to use the update iterator during the tick event.

4.1.7.3 RecUpd Application


An application using this RecordUpdateClient looks almost identical to the application in section 4.1.6.
The allocation of RecordSnapshotClient is simply replaced with an allocation of RecordUpdateClient
as follows:
RecordUpdateClient example(*service, symbol);
This application can be found in the file recupd.C.

SFC Developer’s Guide 52


4.1 SFC MODELS

4.1.8 Field Client


In some programs it is easier to have application components receive events about individual fields
rather than full records. The RecFld example program shoes how to register interest in a single field.
The TickerClient class is similar to the RecordUpdateClient but is more particular about which field
data is displayed. The purpose of the class is to display the value of four fields from the record: the
name of the underlying instrument, the bid price, the ask price, and, when it changes, the trade price.
In addition to being a RTRRTRecordClient, TickerClient is a descendant of RTRRTFieldClient. This
allows an instance of TickerClient to register with the price field of the record being monitored. When a
field level update is received, a flag is set in order to modify the output of the
processUpdateComplete() method (a record generates events before and after the individual field
updates).
Snapshot fields do not receive events, so there is no corresponding example for a snapshot record
and fields.
Also, SFC always requests full records from the market data infrastructure. So, SFC uses record
clients to determine which market data items are actively being watched. Field clients will only receive
updates as long as a least one record client exists for the same item from the same service.
See the RecFld example program for more details.

4.1.9 Pool Client


Previous examples have relied on a single service instance, created by the application. This section
illustrates the use of a pool of services. This example makes use of record clients of type TickerClient
which, as described previously, take at construction a record service instance. The main difference is
in the way the service instances provided to the TickerClient are obtained. In addition, this application
makes use of the configuration capabilities of the SFC. These capabilities are fully explained in section
4.8.5.

4.1.9.1 Declaration for TickerMonitor (tickmon.h)


The purpose of the TickerMonitor class is to monitor a pool for a particular service and, when that
service is available, to create a number of TickerClient instances. The records monitored are
determined by the contents of a configuration variable which is interpreted as a list of symbols. In the
Ticker example, the pool used by TickerMonitor is created by a service pool factory.

SFC Developer’s Guide 53


4.1 SFC MODELS

TickerMonitor is a descendant of RTRRTRecordServicePoolClient. This allows TickerMonitor to


register with a pool and receive relevant events. In this case, TickerMonitor monitors "ServiceAdd"
events by providing an implementation of processRTRecordServiceAdd().
//
// This file contains the declaration of TickerMonitor which
// illustrates the basic techniques for processing service pool events. In
// addition, the use of the RTRConfig and RTRConfigDb are illustrated.
//
// This class is designed to monitor a given pool for a particular service.
// Once that service is available, an instance of TickerClient is created
// for each symbol in a list.
//
// The name of the service and the contents of the symbol list are
// configurable.
//
#ifndef _tickmon_h
#define _tickmon_h

#include "rtr/rtrecspl.h"// Defines RTRRTRecordServicePoolClient


class RTRObjectId; // Forward declaration
class TickerClient; // Forward declaration

typedef TickerClient *TickerClientPtr;

class TickerMonitor :
public RTRRTRecordServicePoolClient
{
public:
// Constructor
TickerMonitor(
const RTRObjectId& context,
const char *name,
RTRRTRecordServicePool& pool);

// Destructor
~TickerMonitor();

// Event processing - from RTRRTRecordServicePoolClient


void processRTRecordServiceAdd(

SFC Developer’s Guide 54


4.1 SFC MODELS

RTRRTRecordServicePool&,
RTRRTRecordService&);

protected:
// Implementation attributes
const RTRObjectId _instanceId;
RTRString _serviceName;
RTRRTRecordServicePool& _pool;
int _tickCount;
TickerClientPtr *_tickStore;

// Static data members


static RTRObjectId _classId;

};
#endif

4.1.9.2 Definition of TickerMonitor (tickmon.C)


The constructor of TickerMonitor extracts from the configuration database the name of the service to
be used and checks to see if that service is already in the pool. If not, there is nothing to do but wait for
the service to appear. The event processing method obtains the list of symbols from the configuration
database and allocates a TickerClient for each symbol. Once the service has been obtained, pool
events are no longer of interest to TIckerMonitor. Note that the destructor of TickerMonitor illustrates
the proper cleanup procedure.
#include "rtr/config.h"// Defines RTRConfig

#include "tickmon.h"
#include "tickclient.h"

// Constructor
TickerMonitor::TickerMonitor(
const RTRObjectId& context,
const char *name,
RTRRTRecordServicePool& pool)
: _instanceId(context, name), _pool(pool),
_tickCount(0), _tickStore(0)
{

SFC Developer’s Guide 55


4.1 SFC MODELS

// Get the name of the service to use


// 1
_serviceName = RTRConfig::configDb().variable(
_classId,
_instanceId,
"service_name",
"IDN_SELECTFEED");
// Register with the pool and see if the desired service is in the pool
// 2
_pool.addClient(*this);
RTRRTRecordService *service = _pool.service(_serviceName);
if (service)
processRTRecordServiceAdd(pool, *service);
}
// Destructor
TickerMonitor::~TickerMonitor()
{
// Be sure to de-register this client from the pool
if ( _pool.hasClient(*this) )
_pool.dropClient(*this);
for ( ; _tickCount; )
delete _tickStore[--_tickCount];
delete [] _tickStore;
}

// Event processing

// 3
void TickerMonitor::processRTRecordServiceAdd(
RTRRTRecordServicePool&,
RTRRTRecordService& service)
{
if (_serviceName == service.name())
{
// 4
// Get a list of symbols to retrieve
RTRListOfExternalValue ricList = RTRConfig::configDb().variable(
_classId,
_instanceId,
"symbol_list",

SFC Developer’s Guide 56


4.1 SFC MODELS

"RTRSY.O").list(‘,’);

_tickStore = new TickerClientPtr [ricList.count()];


// Iterator over the items in the list
for (ricList.start(); !ricList.off(); ricList.forth())
{
_tickStore[_tickCount++] =
new TickerClient(service, ricList.item());
}

// 5
_pool.dropClient(*this);
}
}

// 6
RTRObjectId TickerMonitor::_classId("TickerMonitor");

// 1 TickerMonitor uses the configuration database to determine the name


// of the service from which to access data. The first argument is
// the class identifier of this component (roughly the equivalent to the
// C++ class name), a value which is the same for all instances of this
// class (supposing there were more than one in the application). The
// second argument is the instance identifier of this instance. It should
// be unique to this particular instance of TickerMonitor. The third
// argument is the name of the variable and the fourth argument is the
// default value (as a string) of that variable.
//
// 2 Descendants of RTRRTRecordServicePoolClient may register with a pool to
// receive events from that pool.
//
// 3 This method will be called everytime a new service is added to the pool
//
// 4 The list of symbols is retrieved from the configuration database using
// the same class and instance identifiers but with a different variable
// name and a default value of "RTRSY.O". In addition, the return value
// is further interpreted as a list, delimited by the ‘,’ character.
//
// 5 In this case, addition pool events are of no further interest so
// this client un-registers from the pool.

SFC Developer’s Guide 57


4.1 SFC MODELS

//
// 6 One way to define a class identifier common to all instances of a
// class is to use the static data member construct.

4.1.10 Chain Client


Applications that use the chain model may be interested in all of the data for all of the records in a
chain. However, this is not always feasible, especially for large chains. So some applications initially
take interest in only the list of records in a chain and will request data for just those records that are
currently being displayed.
Chain client components can normally be broken into two parts:
1. the component interested in the chain’s list.
2. the component interested in the record data referred to by elements in the chain.
The ChainUpd example is split in just such as manner. The ChainUpdChainClient class is interested in
the list. Based on events that it receives, it creates and destroys ChainUpdRecordClients, which each
monitor a single field in a single record. Figure 4.9 shows how the classes in the ChainUpd example
are related to SFC client classes.

SFC Developer’s Guide 58


4.1 SFC MODELS

RTRRecordChainElementClient RTRRTRecordClient

RTRRecordChainClient RTRRTFieldClient

ChainElementRecordClient

ChainUpdChainClient * ChainUpdRecordClient

Figure 4.9: Classes in ChainUpd

4.1.10.1 ChainElementRecordClient
Figure 4.9 includes one class that has not been mentioned yet, ChainElementRecordClient.
ChainElementRecordClient merges implementations of a RTRRecordChainElementClient and a
RTRRTRecordClient.
The elements in statistical chains, like .AV.O and .NG.L, often change. Remember that chain elements
are fixed to a position, not a record symbol. So when statistical chains re-sort or resize, the
RTRRecordChainElementClients have to react. Actions are require when:
• the chain shrinks, causing some elements to be removed
• chain elements update, causing some elements to point to new records
In ChainElementRecordClient, these events result in:
• dropping all references so the client’s element and record can safely be deleted

SFC Developer’s Guide 59


4.1 SFC MODELS

• dropping interest in one record and adding interest in another


These actions are reasonably generic, so they have been abstracted into ChainElementRecordClient,
thus keeping the market data logic separate from the display code of ChainUpdateRecordClient (albeit
simple cout <<’s). It should also be noted that ChainElementRecordClient is generic enough that it is
also used by the GUI quote display example for Windows.

SFC Developer’s Guide 60


4.2 SFC MODELS

4.2 Record Publication

4.2.1 Overview
Section 4.1, Record Subscription, described the basic characteristics of real-time record data and how
application components subscribe to that data. These real-time record characteristics remain the same
for publishing and this section assumes that the Record Subscription section has already been read.
The main difference between the models for record publication and subscription is that the publication
model adds new methods to allow application components to "write” to the record. Specifically, the
publication model allows applications to:
• control the contents of a record service
• determine the contents of a service’s constituent real-time records
• update the data of real-time records
• change the state of the service and records
• propagate data and state change events to other interested application components at the record,
field and service level
• provide entitlement data and associated events to other interested application components for
each record

NOTE: This model is used to publish records which represent market data instruments.

The data provider is the application component that interacts with the record publication model. The
application developer creates the data provider component.

4.2.1.1 Published Records


A published real-time record publishes real-time "logical” or record-oriented data (i.e. the data item is
composed of logical fields) representing a market data instrument.
A published record is comprised of 1 to N fields that are created by the data provider and put into the
published record. There are several different type-specific fields available in the SFC for alphanumeric,
date-time, enumerated, integer, numeric, and price values. These type-specific fields provide the

SFC Developer’s Guide 61


4.2 SFC MODELS

capability to interpret the stored field string value according to the rules associated with its particular
type.
A field definition database (fidDb) defines the set of all possible fields that may be added to a published
record. A field definition defines the semantic meaning of a record field, including the name, numeric
identifier (FID), type and maximum data length of a field. Every field in a record is provided a field
definition when the field is created.
A published record may change state depending on the ability of the data provider to supply up-to-date
record data.The published record data may also change as updates are made to the data. Each of
these types of state changes result in events being propagated to downstream client components.

NOTE: A record propagates both state change events and data change events. State changes
reflect the overall state of the record and all constituent fields. Data change events reflect updates to
some or all constituent fields in a record.

In the SFC model, a RTRRTRecordImpl class represents a published real-time record. This class
provides public methods that are used by application components to populate a real-time record with
data, to update the record’s data and to propagate the state and data change events to other
interested application components. Instances of RTRRTRecordImpl are obtained from a service of
type RTRRTRecordServiceImpl.
The main benefits of the RTRRTRecordImpl class are:
• it implements the basic data caching and event propagation code for a real-time record (thus the
name RTRRTRecordImpl)
• it makes it easy to control how the record functions
• it provides a standardized interface for publishing record data to different downstream
components and architectures (e.g. Triarch and RMDS networks)
• it allows application components to stay focused on the task of determining how the record data is
obtained and updated

4.2.1.2 Publishing Service


A publishing service is used to publish record oriented market data to one or more downstream client
components. A publishing service:
• manages requests for new records from downstream clients,

SFC Developer’s Guide 62


4.2 SFC MODELS

• creates new records in response to requests from downstream clients,


• creates new records as directed by the data provider for this service,
• accepts changes to the state of the service and
• propagates service state change events to downstream clients.
Developers create application components that interact with a publishing service and determine how
the service will handle record requests, when the service will transition states, and how published
records will be managed. The application components act as the data provider for the service.
In the SFC model, the RTRRTRecordServiceImpl class represents a publishing service. There are
several different implementations of this service type that publish record data to the Triarch and RMDS
infrastructures and to components within the application. However, application code is written to the
generic RTRRTRecordImpl and RTRRTRecordServiceImpl interfaces.

4.2.2 Design

4.2.2.1 Record Creation


Published records of type RTRRTRecordImpl are created by the data provider for this service and, if
the publishing service implementation permits, by the publishing service (RTRRTRecordServiceImpl)
in response to requests from downstream components.

NOTE: The SFC record publication service implementations always cache the item data that is
being published. Requests from downstream clients for items already cached in the record publica-
tion service will be satisfied from that service without notifying the data provider code.

Records can be added to the service at any time. However, if the publishing service only supports a
source-driven cache (like the TIB implementation), then it is best to load all the records into the
publishing service at application start-up to ensure that these records will be there when the service
becomes available to downstream client components and end-users.

Source-driven mode
A source-driven, or non-interactive, publisher determines the entire contents of the publishing service
cache on its own. Input is not accepted from downstream components.

SFC Developer’s Guide 63


4.2 SFC MODELS

A data provider can use the RTRRTRecordServiceImpl::newRTRecordImpl() method to create a


new RTRRTRecordImpl instance in the service for a specific instrument name (also known as a
symbol). Note that the record must not exist in the service prior to making a newRTRecordImpl()
method call. A reference to the newly published record is returned and the data provider initializes the
state and data for the record (see the RTRRTRecordImpl section of the SFC Reference Manual).
A source-driven publisher has the ability to populate the cache of a 4.2 Source Distributor or later
(Market Data Hub component). From the perspective of the SFC Developer this action is virtually
transparent, but there are some configuration issues that may arise (see section 5.4.5.2 for details).
The *criteriaName configuration parameter is provided to set the criteria request name that is allowed
to request data from a source application. This parameter must match the criteria request name
configuration of the Source Distributor to allow the Source Distributor to request data. The default
value is "triarch".

NOTE: After the publisher indicates the service as sync, if client requests a record that has not been
sent out to the Source Distributor by the publisher, this client will get the record status as inactive.
As a result, this client has to re-request this record.

Sink-driven mode
A sink-driven, or interactive, publisher determines the entire contents of the publishing service cache
based on requests from downstream components.
The publishing service can also create new published records itself based on demand from
downstream components. Note that not all publishing service implementations necessarily support this
capability. The data provider component must register with the publishing service to receive an event
whenever a record not currently cached in the publishing service is requested by a downstream
component. Only a descendant of RTRRTRecordServiceImplClient can register with the service via
the RTRRTRecordServiceImpl::setClient() method. Note that there is one and only one event client
for a RTRRTRecordServiceImpl instance.
When a new RTRRTRecordImpl instance is created due to user demand, the
RTRRTRecordServiceImplClient::processNewRecord() method is invoked by the service. This
method is implemented in the data provider code. The data provider may choose to allow or disallow
the record in the service’s cache. This decision may be made during the event call-back or at a later
time if the data provider needs to query an upstream component before deciding.

SFC Developer’s Guide 64


4.2 SFC MODELS

Initially, a new published record is in the Active_stale state. If the data provider determines the record
is valid, it will populate the record with fields and update the record’s state and data as needed (see
section 4.2.2.5).
If the data provider determines that the record is not valid for some reason (e.g. not a valid instrument
or instrument is no longer supported), the data provider sets the record state to Inactive, using the
RTRRTRecordImpl::setInactive() and notifies downstream components of the record state change
using RTRRTRecordImpl::indicateInactive(). If the data provider wishes to provide the record for
that symbol later on, it must first remove the record from the publishing service via the
RTRRTRecordServiceImpl::removeRTRecordImpl() method. Then it can create a new record and
add it to the service.

Mixed mode
An application can also be designed to load items into the publishing service cache and accept
requests from downstream components for new records as well. To do this, the application simply uses
both of the methods described above.
Note that certain implementations do not support for the sink-driven mode. In particular, the TIB
implementation will only allow the source-driven mode to be utilized. This means that the typical
application using TIB will need to publish all of its records during initialization so they will be available
when the application goes live on the RMDS network on a TIBCO Rendezvous Distribution Layer.
Note that your application can still be designed to use the sink-driven mode, but when used with the
TIB implementation, it will never receive requests from downstream components.

4.2.2.2 Record State Diagram


The state of a real-time record is defined by the values of three record attributes:
• active
• hasData
• stale
These state variables allow downstream users to determine whether the record is valid, whether the
record has been populated with its set of fields, and whether the data is currently up-to-date.
Figure 4.10 shows record states and the events that indicate transitions between states:

SFC Developer’s Guide 65


4.2 SFC MODELS

Sync Resync
Active_noData Active_valid
Inactive
Sync
Inactive NotStale
Stale

Inactive Active_stale
Inactive
Resync
Active_noData (hasData = False, stale = True, active = True)
Active_valid (hasData = True, stale = False, active = True)
Active_stale (hasData = True, stale = True, active = True)
Inactive (hasData = XX, stale = XX, active = False)

Figure 4.10: Real-time Published Record - States, Transitions and Variables

4.2.2.3 Record State Change Events


Record state may change as the record transitions through initialization, data provider data-loss and
recovery conditions, and end-of-life for the record. As transitions occur in the state of the record, the
data provider will change the record’s state variables and then propagate state change events to
downstream client components. Following are descriptions of the state transition events:
• Sync - This event indicates the availability of an initial "image”. This event is propagated after the
data provider has added all fields to a record and provided the initial data for each field. The
RTRRTRecordImpl::indicateSync() method is called to send this event.
• Resync - This event indicates the record data is about to be refreshed. This event can indicate a
change in state from Active_stale to Active_valid, but it is the responsibility of the downstream
client component to check whether the record state has changed. This event can be used to

SFC Developer’s Guide 66


4.2 SFC MODELS

indicate an update to fields due to recovery from a data-loss condition. The


RTRRTRecordImpl::indicateResync() method is called to send this event.
• ResyncComplete - This event indicates that the record data has been refreshed. Downstream
client components will access the fields that have changed during this call. The
RTRRTRecordImpl::indicateResyncComplete() method is called to send this event.
• Stale - This event indicates a transition from the Active_valid state to the Active_stale state. All
field data is considered out-of-date when the record makes this transition. It is the responsibility of
the data provider to recover the data in a timely fashion. This event can be used when the record
data is no longer up-to-date. The RTRRTRecordImpl::indicateStale() method is called to send
this event.
• NotStale - This event indicates a transition from the Active_stale state to the Active_valid state. All
field data is considered up-to-date when the record makes this transition. This event can be sent
after the record data has been brought back up-to-date. The
RTRRTRecordImpl::indicateNotStale() method is called to send this event.
• Inactive - This event indicates a transition to the Inactive state. This event can be sent when the
record is no longer valid, such as when requests are made for non-existent items or when a
request cannot be satisfied due to entitlements restrictions. This is a permanent condition; the
record cannot be transitioned out of this state. The RTRRTRecordImpl::indicateInactive()
method is called to send this event.

NOTE: A transition to the Inactive state is a permanent condition. It is meant to indicate that this
record will not be available anymore. If a record is temporarily unavailable, it should be put into the
Stale state, not the Inactive state.

Records have a text() method which provides a textual explanation of the current record state. Record
clients are kept informed of progress by means of events which indicate that there is new textual data
available concerning the state of the record.
A record will also generate informational events when appropriate. The record’s text() should be
changed to describe the informational event. This event is used to pass on information that may be of
interest to downstream client components. This might include information regarding progress
ininitializing the record data or in recovering record data. These events never indicate a change in
record state. The RTRRTRecordImpl::indicateInfo() method is called to send this event.

SFC Developer’s Guide 67


4.2 SFC MODELS

4.2.2.4 Record Data Change Events


The constituent fields of a record may change over time at the discretion of the data provider
component. These field-level data changes manifest themselves at the record level as updates or
"ticks”. These ticks are manifested by events which are initiated by the data provider and are
propagated from the RTRRTRecordImpl instance to all interested downstream clients of the record.
Each tick indicates a change to one or more fields of a record. There are pre-tick and post-tick events
generated with each tick. The pre-tick events (CloseTick, CorrectionTick, Tick) indicate that the some
fields are about to be updated and indicate the type of update that will occur. The post-tick event
(UpdateComplete) indicates that the fields have been updated and that a list of the updated fields is
now available to downstream client components.
Following are descriptions of the data change events:
• CloseTick - This update event indicates that the fields modified by this update are not changing as
a result of market activity, but rather as a reflection of changes in certain historical fields. For
example, a field which reflects the closing price for the previous day’s trading will be updated by a
close tick prior to a new day of trading. This event is initiated by the data provider prior to updating
individual fields which are affected by this tick. The RTRRTRecordImpl::indicateCloseTick()
method is called to send this event.
• CorrectionTick - This update reflects corrections to previously delivered data which is in error.
Updates of this type do not indicate market activity. This event is initiated by a data provider prior
to updating individual fields which are affected by this tick. The
RTRRTRecordImpl::indicateCorrectionTick() method is called to send this event
• Tick -This update reflects an update to record data due to market activity. This event is initiated by
a data provider prior to updating individual fields which are affected by this tick. The
RTRRTRecordImpl::indicateTick() method is called to send this event.
• UpdateComplete -This event is initiated by the data provider after all fields affected by a tick have
been modified. This event must be sent after field data has been updated. The
RTRRTRecordImpl::indicateUpdateComplete() method is called to send this event.
Field-level events are generated by the data provider immediately after field data is updated. The
FieldUpdate event is propagated through individual RTRRTField instances to downstream
components that have registered interest with the field. Field events may only occur between a pre-tick
and post-tick event for the associated record.

SFC Developer’s Guide 68


4.2 SFC MODELS

See section 4.1.1.7 on Record Clients for information on how events are typically handled in
downstream client components.

4.2.2.5 Record Initialization


After the data provider component initially obtains a RTRRTRecordImpl instance, it must initialize the
record. The basic algorithm for initializing a record is:
Create new fields and put them into the published record
Set the descriptive text of the published record
Send a Sync event for the record
Initially, the RTRRTRecordImpl instance (published record) obtained from a publishing service is in the
Active_noData state (hasData=False and stale=True). Refer to the state diagram in Figure 4.10. This
initial state indicates that the record has not yet been populated with fields. It is the responsibility of the
data provider to populate all the fields associated with the record. This is done by creating instances of
the defined field types and adding them to the record with the RTRRTRecordImpl::putField() method.

NOTE: Fields can be added to records at any time. Down stream clients will only receive these new
fields if the publisher calls either RTRRTRecordImpl.indicateSync() or RTRRTRecordImpl.indi-
cateResyncComplete(RTRRTFieldUpdateList & fldList). On the client side this added field will
not be contained in the RTRRTRecordUpdateIterator and will only show up in the RTRRTRecordIt-
erator during the clients RTRRTRecordClient::processResyncComplete() callback.

Adding fields after a record transitions out of the Active_noData state is not supported when record
templates are used. Adding fields may work if the added field is in the template, however if the field
is not in the template the RTIC will not cache the field.

The defined field types are: RTRRTPriceField, RTRRTEnumeratedField, RTRRTIntegerField,


RTRRTNumericField, RTRRTAlphanumericField, and RTRRTDateTimeField, RTRRTField.
When creating one of the defined field types, the data provider must supply several parameters to the
field constructor:

SFC Developer’s Guide 69


4.2 SFC MODELS

• A RTRFidDefinition instance that properly represents that field. This means that the
RTRFidDefinition::type() must match the type of field being created as indicated in the following
table:

RTRFidDefinition::type() Field type to use

TimeSecs,Time,DateTime RTRRTDateTimeField

Integer RTRRTIntegerField

Numeric RTRRTNumericField

Price RTRRTPriceField

Enumerated RTRRTEnumeratedField

Alphanumeric, LongAlphanumeric RTRRTAlphanumericField

Binary RTRRTField

Table 4.7: Mapping of RTRFidDefinition::type() and Field Types

The FID definition is obtained from the service that created the published record
(RTRRTRecordServiceImpl::fidDb()).
• A character array that will be used by the field to store data. Both the character array and the
length of the array are passed.
• The length of the allocated memory. This should be the maximum length defined by the FID
definition (i.e. RTRFidDefinition::length()) plus 1 byte to accommodate an end-of-delimiter
character in the field data. Note that this is not the size of data currently found in the buffer, but the
maximum size of the buffer.

NOTE: When allocating memory for the field, you must allocate 1 extra byte to accommodate an
end-of-field delimiter; e.g. "char* buf = new char[ fidDef->length() + 1]”. If the correct length is not
supplied, the field may not include all of the data.

After allocating the field, the initial data value is set using the RTRRTField::set() method.

SFC Developer’s Guide 70


4.2 SFC MODELS

After the record is fully populated with fields, the state of the record should be changed to either
Active_stale or Active_valid. The record data can be either stale or up-to-date when a Sync event is
propagated. The RTRRTRecordImpl::setNotStale() method is used to change the record data state
from stale to notStale. This must be done prior to sending the Sync event. Also, the
RTRRTRecordImpl::setText() method may be used to reset the descriptive text associated with the
record.
The RTRRTRecordImpl::indicateSync() method is called to propagate the Sync event to
downstream client components. The RTRRTRecordImpl::hasData() record state variable will
automatically be transitioned to True on this call.

NOTE: A transition from the Active_noData state occurs only once during the lifetime of the record.
Future re-synchronization of the record is indicated by sending Resync and ResyncComplete
events (see section 4.2.2.8).

4.2.2.6 Updating Fields in a Published Record


At some point after the record is initialized, one or more fields may need to be updated as market
movement occurs. The general algorithm for updating record fields is:
Notify downstream clients that fields are about to be updated
Create/re-initialize a field update list of type RTRRTFieldUpdateList
For each field to be updated
Update the field data as required (using the RTRRTField.set() method)
Notify field clients that the field data has changed
Add the updated field to a field update list
End for each field
Notify downstream record clients that fields have been updated
There are two discrete events associated with updates to record fields. The first event indicates that a
particular type of update is about to occur to some fields in the record. The RTRRTRecordImpl::
methods indicateUpdateTick(), indicateCorrectionTick() or indicateCloseTick() are used to
indicate a particular type of update event.

SFC Developer’s Guide 71


4.2 SFC MODELS

The data provider then updates the fields that have changed. Each field that is to be updated is
obtained from the record using one of the record’s field accessor methods. Fields are then updated by
calling the RTRRTField::set() method and providing the new data for the field.

NOTE: If a length value of 0 is given to the RTRRTField::set() method, the field data will be cleared.

If the length value given to the RTRRTField::set() method is greater than the maximum length pro-
vided to the field at construction, the provided data will be truncated at the maximum length of the
field.

After the appropriate fields have been updated, the indicateUpdateComplete() method is called. This
method takes a RTRRTFieldUpdateList reference which is used as a container for the fields from this
record that have been updated. The RTRRTFieldUpdateList class provides methods to insert fields by
name, by FID or by reference. Upon completion of the indicateUpdateComplete() method, all of the
record’s registered event clients have been notified of the updates to the fields passed in the field
update list.

HINT: It is a good idea to keep a RTRRTFieldUpdateList in memory and re-initialize it as needed


rather than creating a new one for each update loop.

4.2.2.7 Changing Record State


After a Sync event occurs, the only valid state changes for a real-time record are:
• Active_stale to Active_valid
• Active_valid to Active_stale
• Active to Inactive
The general algorithm for changing the state of a record is:
Reset the state of the record
Set new informational text for the record
Notify downstream client components of the specific state change
To change a record’s state, the record is first set to its new state using one of the setStale(),
setNotStale or setInactive() methods. Next, typically, the setText() method is used to provide a
reason for the state change. Then the state transition is propagated to downstream client components
using the indicateStale(), indicateNotStale() or indicateInactive() methods.

SFC Developer’s Guide 72


4.2 SFC MODELS

Note that the transition from Active to Inactive represents a permanent state change and that the
record is no longer valid. No more data or state changes may occur to the record once it has
transitioned to the Inactive state. Typically, the record is removed from the service (using the service’s
removeRTRecordImpl() method) after the Inactive event is propagated to downstream client
components.

4.2.2.8 Resynchronizing Record Data


Data may need to be resynchronized if the data becomes out-of-date for some reason, like failure of an
upstream data source feed. A record is resynchronized using the same procedure as an update,
except that the Resync and ResyncComplete events are sent and the state of the record may be
changed in conjunction with the events.
The general algorithm for resynchronizing a record is:
Notify downstream clients that fields are about to be updated
Create/re-initialize a field update list of type RTRRTFieldUpdateList
For each field to be updated
Update the field data as required
Notify field clients that the field data has changed
Add the updated field to a field update list
End for each field
Notify downstream record clients that fields have been refreshed

There are two discrete events associated with refreshing record fields. The first event indicates that a
resync is about to occur and zero or more fields will be updated in the record. The method
RTRRTRecordImpl::indicateResync() is called to send a Resync event. The second event indicates
that the fields associated with the refresh have been updated and a list of the changed fields is
available. The RTRRTRecordImpl::indicateResyncComplete() is called to send a ResyncComplete
event.

4.2.2.9 Access to Published Records


A RTRRTRecordServiceImpl provides the publisher both "random” and sequential access to its cache
of records. Random access is achieved by calling the RTRRTRecordServiceImpl::rtRecordImpl()
method and providing the symbol name of the instrument.

SFC Developer’s Guide 73


4.2 SFC MODELS

Sequential access is achieved by obtaining an iterator from the record with the
RTRRTRecordServiceImpl::iterator() method. An instance of RTRRTRecordServiceImplIterator
provides access to all the published records within a record.

4.2.2.10 Publishing Service State Changes


The state of a publishing service is determined by the value of two attributes: stale and active. The
three valid service states are defined as follows:

Record
State Description
Attributes

Stale stale = True The service is not capable of providing up-to-date


active = True data. This can occur if the data provider’s data source
becomes unreliable (lost connection, slow data flow,
innacturate data, etc.). All of the constituent records
must be changed to the Stale state also. Stale is a
recoverable condition and it is the responsibility of the
data provider to recover all constituent records. Items
may be requested from stale services, but the items
will remain stale until the service itself is no longer
stale and can automatically recover the items.

A GroupStale is a side effect of service stale. When a


service transitions to stale, SFC will automatically trig-
ger a GroupStale. (There is only one group in SFC, so
all items in that service are stale.) Publishing to the
network is disabled. Items can only be published to
publisher’s cache while the service is stale. Also, any
insert objects in the service that have not been
acknowledged will be N-ACKed and deleted.

Table 4.8: Publishing Service States

SFC Developer’s Guide 74


4.2 SFC MODELS

Record
State Description
Attributes

Ok stale = False The service is now capable of providing up-to-date


active = True data and will recover any cached items.

A GroupNotStale will be sent when the service transi-


tions from Stale to Ok. Any items in the cache will be
marked Ok as well. Publisher is allowed to publish to
the network.

Inactive stale = don’t care The service is being deactivated. All constituent items
active = False in this service must also be changed to the Inactive
state. Users across a Triarch network will be notified
that the service is Stale (not Inactive, since other ser-
vices on the network with the same name may be
available to handle user requests). Users on an RMDS
network on a TIBCO Rendezvous Distribution Layer
will receive individual inactives. Users within the same
process must drop all references to this service as this
is a non-recoverable condition.

Table 4.8: Publishing Service States (Continued)

The data provider component is responsible for determining the current state of the publishing service.
State transitions are propagated to clients as events generated by the data provider. The events
triggered by state transitions are described as follows:
• Sync - This event indicates that the service is ready to accept requests and will recover data for
any items currently cached in the service. Unlike the record sync event, this event can occur
multiple times for a given service instance. However, it will never occur twice in a row. This event
triggers a transition from the Stale state to the Ok state. Triarch and in-process service clients will
receive a processServiceSync() event. This will also allow publisher to publish to the network.
• Stale - This event indicates a transition from the Ok state to the Stale state. Triarch and in-process
service clients will receive a processServiceStale() event. Publishing to the network is disabled.
(Network connection is still up). The publisher can still publish data; however, the data will only go
to the publisher’s cache. Also, any inserts in the cache are N-ACKed and deleted.

SFC Developer’s Guide 75


4.2 SFC MODELS

• Inactive - This event indicates a transition to the Inactive state. In-process service clients will
receive a processServiceInactive() event and should release all references to the service but
this inactive event will not be propogated across the network. Consumers will recieve stale
events.
Two methods are available for sending group messages efficiently to downstream clients.
• GroupStale - This event indicates Stale for all records in a particular group. This event can be
used to efficiently send stale notifications to all records of a group. The indicateGroupStale()
method is called to send this event. Unlike a service stale, a GroupStale still allows the publisher
to publish to the network. However, all the items published to the network are stale.
• GroupNotStale - This event indicates NotStale for all records in a particular group. This event can
be used to efficiently send NotStale notifications to all records of a group. The
indicateGroupNotStale() method is called to send this event.
Services will also generate informational events when appropriate. Triarch and in-process service
clients will receive a processServiceInfo() event. These events never indicate a change in the
service’s state. Services have a text() method which provides a textual explanation of the current state
of the service.

SFC Developer’s Guide 76


4.2 SFC MODELS

Figure 4.11 shows the various service states and state transitions.

Stale Sync

Stale
Inactive Ok

Inactive
Inactive

Stale (stale = True, active = True)


Ok (stale = False, active = True)
Inactive (stale = XX, active = False)

Figure 4.11: Publishing Service - States and Variables

4.2.2.11 Publishing Entitlement Data


Some publishing applications are required to provide entitlement data for each item that is published.
The entitlement data can be used by downstream components to determine whether a given user is
allowed to access the data for a particular item from that service.

NOTE: Some DACS specific configuration must occur in order for respective entitlement data to be
published properly. See section 5.3 Entitlements for implementation specific details.

Overview
The RTRRTRecordImpl class provides methods to set entitlement data for each record and to
propagate an event indicating the existence of the entitlement data. The
RTRRTRecordImpl::setEntitlementData() method is used to set new entitlement data. The
entitlement data is passed in the form of an RTREntitlementData object. After setting the entitlement
data, the RTRRTRecordImpl::indicateEntitlementData() is used to propagate an EntitlementData

SFC Developer’s Guide 77


4.2 SFC MODELS

event to downstream components. This event indicates that entitlement data or updated entitlement
data is available for the record.
The RTREntitlementData class encapsulates a buffer containing the entitlement data and a format
attribute which identifies the format in which the entitlement data is encoded. A pre-defined format
(RTREntitlementData::DacsAccessLockFormat) is provided for using the DACS entitlement
system, the standard entitlement system for RMDS. The purpose of the format attribute is to allow
different entitlement data formats to be provided in the future.
The following code segment shows how entitlement data is created with a DACS access lock, then
published to a record. This code segment assumes that a DACS access lock has already been created
and that the appropriate RTRRTRecordImpl instance has been obtained:

SFC Developer’s Guide 78


4.2 SFC MODELS

#include "rtr/rtrecimp.h"

// int lockLength;
// unsigned char* lockPtr;
// RTRRTRecordImpl& publishedRec;

RTREntitlementData *edata = 0;

edata = new RTREntitlementData( RTREntitlementData::DacsAccessLockFormat,


lockPtr,
lockLength);
publishedRec.setEntitlementData( edata );
publishedRec.indicateEntitlementData();
delete edata;
Entitlement data can be set on a record at any time during the life of the record. However, in order to
ensure that downstream users are only allowed access to data for which they are entitled, entitlement
data must be provided before the initial image is published for the record. After the record and
entitlement data are cached, the SFC record publishing implementation will respond to further
requests for that record by first sending any entitlement data associated with the record and then
sending the image.
Entitlement data can also be updated later at the discretion of the data provider. The new entitlement
data must be set in the record and another RTRRTRecordImpl::indicateEntitlementData() call must be
made to propagate an EntitlementData event to downstream components.
For more details on how to set up your system to publish entitlement data and more implementation
details, see section 5.3.

4.2.2.12 Managing Record Resources

Overview
Data provider components that are interactive typically find it useful to know when interest in a given
record has been added or dropped. One possible use for these events would be to remove records
that have not been actively monitored for some period of time.

SFC Developer’s Guide 79


4.2 SFC MODELS

To receive interest add and drop events from RTRRTRecordImpl, the data provider component
registers with the published record. The registered published record client will then receive events
whenever the first client adds interest in the record and when the last client drops interest in the record.

NOTE: Not all implementations of RTRRTRecordImpl support interactive, sink-driven requests for
items. Therefore, registered data provider components may or may not receive these notifications
depending on the particular implementation of RTRRTRecordImpl being used. See

The typical use of this capability is to better manage memory and CPU resources by removing records
that are not being used by downstream clients. Note that the actual number of downstream clients
using the item is not available to the data provider component; this information may not be available to
the published record as it may be publishing to a distributed network.

Registering and receiving client interest events


A data provider component may receive events from an instance of RTRRTRecordImpl by inheriting
from RTRRTRecordImplClient and registering with the record using the
RTRRTRecordImpl::addClient() method. Once registered, the data provider component will receive
events indicating either the presence or absence of interested downstream client components for the
published record.
The processHasEventClient() method is invoked by the published record when a transition from no
interested clients to one or more interested clients has occurred. The processNotHasEventClient()
method is invoked by the published record when a transition from one or more interested clients to no
interested clients has occurred.
The data provider component can also use the RTRRTRecordImpl::dropClient() method to
deregister for the client interest events.

4.2.3 Class Summary


This section provides a summary of the classes which comprise the model for publishing real-time
record data. For more details please refer to the appropriate sections of the alphabetical class
reference.
• RTRRTRecordImpl - This class defines an item of real-time record data. Record
implementations provide methods used both to populate fields in a record and to access the fields
either sequentially or in random fashion. Record implementations have state which may change
over time. Data and state change events are propagated to other application components which

SFC Developer’s Guide 80


4.2 SFC MODELS

have registered with a record for the purpose of receiving record data and state change events.
Record implementations have their own event clients that are notified whenever the number of
consumers monitoring the record transitions from zero to one or from one to zero. There may be
multiple clients of a record implementation.
• RTRRTRecordImplClient - This is the abstract base class for application components which
wish to register with one or more real-time record implementations in order to receive data and
state change events from those records.
• RTRRTRecordImplIterator - Instances of this class provide sequential access to all the
constituent fields within a given record implementation.
• RTRRTFieldUpdateList- Instances of this class are used during update events to provide
sequential access to those fields within a real-time record implementation that have been
modified.
• RTRRTField - This class defines the base type for the constituent parts of a record. Fields are
identified by name or FID, have a specific type, and provide various forms of access to the
underlying data which they represent.
• RTRRTAlphanumericField, RTRRTDateField, RTRRTEnumeratedField, RTRRTIntegerField,
RTRRTPriceField - These descendants of RTRRTField provide type-specific interpretation of the
underlying data. These instances are created by the data provider and added into a record
implementation instance.
• RTRRTRecordServiceImpl - This class provides methods used by application components to
control the creation/deletion of record implementations, to manipulate the state of the service, and
to propagate state change events to interested service consumers. A RTRRTRecordServiceImpl
implements all the caching and memory management of record implementations.
• RTRRTRecordServiceImplClient - This is the abstract base class for components that need to
register with one or more instances of record service implementation in order to receive state
change events whenever a new record is added to the service due to service consumer demand.
• RTRRTRecordServiceImplIterator - Instances of this class provide sequential access to all the
constituent published records within a given publishing service implementation
• RTRFidDb - This class represents the database of field definitions used by a particular service.
• RTRFidDbClient - This is the abstract base class for components that need to register with a
RTRFidDb to receive events when the database has completed initialization or when an error has
occurred while initializing the database.

SFC Developer’s Guide 81


4.2 SFC MODELS

• RTRFidDefinition - This class represents the definition for an individual field. A definition
comprises the identification (name and FID) of a field and the type. The type determines the way
in which the raw data should be interpreted; the identity defines the meaning of the field.
• RTREntitlementData - This class represents entitlement data which is used to entitle users in
downstream components. The class encapsulates a buffer of entitlement data and a format
attribute identifying the encoding format for the data.

4.2.4 Implementation
Currently, the SFC provides three implementations of the record publication classes—an SSL
publisher, a TIB publisher, and an in-process publisher. The names of these publishing service
implementations are based on the relationship of how the data is published into the service and how
the data is published out to downstream client components. Specifically,
• RTRRTFieldToSSLRecordService - publishes records to the SSL infrastructure, to the RMDS
on the Market Data Hub, or to a directly connecting SSL-based application.
• RTRRTFieldToTIBRecordService - publishes records to the TIB infrastructure or to the RMDS
on the Rendezvous Distribution Layer.
• RTRRTFieldToFieldRecordService - publishes records to other in-process components as a
RTRRTRecordService service type.
The following table provides a comparison of the main features of the different publishing service
implementations

SSL TIB In-process


Feature
Publisher Publisher Publisher

Supports source-driven, non-interactive mode X X X

Supports sink-driven, interactive mode X X

Client applications can connect directly to publisher X

Publishing service can be used within the application X X X


process as a RTRRTRecordService object. (E.g. can
be added to a service pool)

Table 4.9: Publishing Service Implementations - Feature Comparison

SFC Developer’s Guide 82


4.2 SFC MODELS

SSL TIB In-process


Feature
Publisher Publisher Publisher

Can publish to 4.2 Source Distributor or later X

Can publish to RTIC in SASS2 mode X

Can publish to RTIC in SASS3 mode X

Can publish in Marketfeed format X

Can publish in TIBMsg self-describing format X

Can publish DACS entitlement data X

Caches items locally X X X

Table 4.9: Publishing Service Implementations - Feature Comparison

4.2.4.1 SSL Publishing Service


The RTRRTFieldToSSLRecordService class provides users with the ability to publish real-time record
data for a single service name to multiple SSL client applications, SSL infrastructure components, and
RMDS Market Data Hub components.
User application code determines exactly which record symbols will be published, where the record
data comes from, and how the data updates and changes state. As a descendant of the
RTRRTRecordServiceImpl, this service inherits methods that let publishing components register for
notifications when users request new records, manipulate the contents of the service record cache and
modify the state of the service.

Client connectivity
Client applications that can connect to this service include any user application using SSL 4.X or
higher libraries and infrastructure components that support connecting into a source application, like
the 4.1.X and higher version of Source Distributor.
In contrast to earlier versions, this publishing service implementation allows client applications to
connect directly to the publishing application. The RTRSSLConnectionServer opens a well-known port

SFC Developer’s Guide 83


4.2 SFC MODELS

("triarch_sink” by default) that client applications connect to using SSL 4.X or higher protocol. From the
perspective of the client application, the SSL publishing service looks like a Sink Distributor.

NOTE: SFC-based client applications can connect directly to an SFC publishing application. This is
new in the 4.1 release.

Multiple instances of publishing services may use the same connection server to allow client
applications to access all services over the same connection. Several different constructors are
available to provide programmers flexibility in choosing which services publish to which port.
The RTRSSLConnectionServer class manages the well-known port that downstream applications use
to establish communications with SSL publishing services. This class is used by SSL publishing
services to find out when new downstream connections have been established so that the publishing
services can be made available on the channel.
For applications publishing a single service, an instance of RTRSSLConnectionServer is typically
created automatically by the publishing service (based on which service constructor is used).
Alternatively, application components can create an instance of this class and pass it to one or more
publishing services. This is typically done when the application is publishing multiple services and
each service needs to share the same downstream connection.
Another reason to create and pass an instance of RTRSSLConnectionServer to publishing services is
if multiple well-known ports will be used on a given machine to publish services. In this case a different
instance of RTRSSLConnectionServer would be created for each publishing service and given
different well-known ports.
By default, RTRSSLConnectionServer uses port service "triarch_sink." This is the default port used by
the Source Distributor (version 4.1 and later) and by SSL and SFC-based end user applications to
access market data.
If the connection server is unable to open the well-known port, it will continue retrying the port at 5-
second intervals and will log a message. This condition would typically occur if another application
already has the port open.

Application structure
Typically, an application is structured so that an instance of RTRRTFieldToSSLRecordService is
created during initialization (the program’s "main” for instance) and then passed to application
components as a RTRRTRecordServiceImpl. This allows the data provider code to focus only on its

SFC Developer’s Guide 84


4.2 SFC MODELS

given task, publishing data via the RTRRTRecordServiceImpl instance. This also hides the
implementation type from the vast majority of your application code, allowing your application to easily
switch between publisher implementations.
After construction, this service will be in the Active/Stale state. It is the responsibility of the
programmer’s application code to determine when the service should transition to Active/NotStale. As
client applications connect to the service, an indication of the state of the service will be sent to the
client application.

4.2.4.2 TIB Publishing Service


The RTRRTFieldToTIBRecordService class provides users with the ability to publish real-time record
data for a single service name to the RMDS network on a TIBCO Rendezvous Distribution Layer.
User application code determines exactly which record symbols will be published, where the record
data comes from, and how the data updates and changes state. As a descendant of the
RTRRTRecordServiceImpl, this service inherits methods that manipulate the contents of the service
record cache and modify the state of the service.
Note that a TIB publishing service is always non-interactive in nature and must publish to an RTIC
process on the RMDS network. This means that the publishing application will not receive notifications
from RMDS when users request items not already cached in an RTIC. The RTIC is not capable of
forwarding item requests to publishing applications. So publishing applications must publish all items
that might be requested by subscriber applications to the RMDS network on a TIBCO Rendezvous
Distribution Layer. Typically this would occur when the application is initialized, before the application
connects to the RMDS network on a TIBCO Rendezvous Distribution Layer. Once the connection to
RMDS is established, the publishing service will send initial images for all cached items to the RMDS.

Mapping SFC symbol names to TIB subject names


When publishing records to an RMDS network on a TIBCO Rendezvous Distribution Layer, SFC tries
to infer the suitable 4-part subject name using the SFC service name and the item name. In cases
where the mapping algorithm does not produce the appropriate 4-part subject name, the application
programmer may override methods in the RTRTIBCustomizer class to provide the name mapping
required by the publishing application. See section 5.5.7 and see RTRTIBCustomizer in the SFC
Reference Manual for more information.
Moreover, while working with RTIC (SASS2), SFC normally prefixes "_TIC." to the subject when
publishing to RTIC(SASS2) (unmanaged publication). The *pubSubjectPrefix configuration allows
control of the character string required to be prefixed to all subjects published to the RTIC(SASS2).

SFC Developer’s Guide 85


4.2 SFC MODELS

The default is "_TIC."; therefore, the SFC publisher would send the subject "_TIC.A.B.C.D" for
publishing of the subject "A.B.C.D" to RTIC.

TIB connectivity
The TIB publishing service will communicate with the RMDS network via the Rendezvous Daemon
(RVD). The connection to the rvd is created and handled by the RTRTIBConnection class. The TIB
connection can be shared with multiple TIB publishing and subscription services.
By default, the TIB publishing service will create a TIB connection using default parameters. The data
provider application may override the default values for these parameters or may create a
RTRTIBConnection and pass it into the service at construction.
An application may have multiple instances of publishing services use the same rvd connection by
creating a single RTRTIBConnection and passing it into each RTRRTFieldToTIBRecordService
instance at construction. Several different constructors are available to provide programmers flexibility
in choosing which services publish through which RVD.
See section 4.8.1 and see the SFC Reference Manual for more information on RTRTIBConnection.

Application structure
Typically, an application is structured so that an instance of RTRRTFieldToTIBRecordService is
created during initialization (the program’s "main” for instance) and then passed to application
components as a RTRRTRecordServiceImpl. This allows the data provider code to focus only on its
given task, publishing data via the RTRRTRecordServiceImpl instance.
After construction, this service will be in the Active_stale state. It is the responsibility of the
programmer’s application code to determine when the service should transition to Active_valid and
when it will start publishing records.

4.2.4.3 In-Process RTRRTRecordService Publisher


The RTRRTFieldToFieldRecordService allows developers to create their own implementation of
RTRRTRecordService for use within an application. As a descendant of the RTRRTRecordService
class, this class provides the standard service interface to consumers of SFC-based real-time record
data. As a descendant of RTRRTRecordServiceImpl, this class provides the standard service provider
interface for populating the service with records.

SFC Developer’s Guide 86


4.2 SFC MODELS

Typically, an application is structured so that an instance of RTRRTFieldToFieldRecordService is


created during initialization (the "main” of the program, for instance) and then passed to application
components as an ancestral type. For instance, the data provider component might take a
RTRRTRecordServiceImpl whereas the data consumer component would take a
RTRRTRecordService. This allows for greater flexibility in changing the implementation type of the
publishing service.
At construction, the state of this service set to Active and Stale. It is the responsibility of a data provider
component to set the service to the NotStale state when it deems appropriate and to handle all events
associated with a publishing service (see RTRRTRecordServiceImpl).
The Field-to-Field implementation allows in-process SFC consumer application components to access
the record and service implementations as RTRRTRecord and RTRRTRecordService instances. The
Field-to-Field implementation effectively "glues” the provider and consumer SFC interfaces together.
The Field-to-SSL implementation publishes record data as an SSL source service, handling all issues
regarding publication via the SSL (like creation of SSL and Marketfeed messages).

4.2.5 Examples
Several sample programs have been provided to show different ways in which a record publisher
application can be constructed.
Figure 4.12 provides a component version of the various interfaces and implementations. Note that the
Data Provider and Data Consumer components are written to the abstract interfaces, then are
"plugged in” with a specific implementation of the abstract interface.
While most application components should refer only to the base classes mentioned in the preceding
section, the "main” routine or initialization section of an application must instantiate one or more
implementation specific classes. Please refer to the alphabetical reference section and the relevant
example programs for more details concerning these classes.
Table 4.10 provides a brief overview of the example applications provided with the software
distribution. A few representative samples of these programs are detailed in the sections following this
table.
You are encouraged to study the examples as a guide to using the SFC record publication classes.

SFC Developer’s Guide 87


4.2 SFC MODELS

Data Flow
The Components

Real-time "Provider” "Consumer” Real-time


Data SFC SFC Data
Provider RealTime RealTime Consumer
Component Interface Interface Component

In-Process Solution

Field
Real-time to Real-time
Data Field Data
Provider Consumer
Implementation
Component Component

Networked Solutions

Real-time SSL Publishing Service SSL Record Service Real-time


Data SSL Data
Provider Implementation NETWORK Implementation Consumer
Component Component

Real-time TIB Publishing Service TIB Record Service Real-time


Data TIB Data
Provider Implementation NETWORK Implementation Consumer
Component Component

Figure 4.12: Component View of the Record Publication Implementations

SFC Developer’s Guide 88


4.2 SFC MODELS

Example
Description Refers To
Program

Simulator Simple application that publishes canned record data simulator.C (main)
based on user requests. This example shows how simrec.C
to: simsrvc.C
• create specific field types fcsimsrvc.C
• properly initialize publishing services and
records (section 4.2.6)
• optionally setting template numbers
• change state and propagate state change
events
• update record data and propagate data
change events
• publish as a sink-driven (interactive) or
source-driven (non-interactive) service.
• create necessary components to publish to
TIB, to SSL, or within an application process

Gateway An application that obtains record data via the sub- gateway.C (main)
scription SFC interfaces and re-publishes the data gatesvc.C
using the publisher SFC interfaces. This example sinkgates.C
shows the same capabilities as the Simulator exam- srcgates.C
ple, plus how to: gaterec.C
• publish data from an asynchronous data
source (an SFC RTRecordService in this (section 4.2.7)
case)
• handle differences in field definitions
between subscription and publication
services
• design a bridging or value-added gateway
application using SFC

Table 4.10: Record Publication Example Applications

SFC Developer’s Guide 89


4.2 SFC MODELS

Example
Description Refers To
Program

Injector An application that extends the gateway application injector.C (main)


by injecting an extra field into each record that is gatesvc.C
republished using the provider SFC. This example gaterec.C
shows the same capabilities as the Gateway exam- injectsvc.C
ple, plus how to: srcinjectsvc.C
• publish value-added data in a gateway injectrec.C
application

Aggregator An application that extends the gateway application aggregator.C (main)


by publishing record updates at specific time inter- gatesvc.C
vals. This example shows the same capabilities as gaterec.C
the Gateway example, plus how to: aggsvc.C
• write a gateway application that supplies srcaggsvc.C
data updates at regular intervals rather than aggrec.C
as the updates occur in the market.

Table 4.10: Record Publication Example Applications (Continued)

This section describes the design and implementation of a new class or "component” and shows how
to use that class in an application.

4.2.6 Simulator Program


All the code and makefiles for this example are available in the product distribution.

4.2.6.1 Requirements
The application must respond to requests from downstream clients for canned record data and
subsequent update and state change notifications. The main purpose of the program is to show the
basics of how to set up a publishing service and use the various methods from the publishing classes.
This application also serves to provide all the different types of events associated with a real-time
record publisher.
This application can be used as a starting point for most user applications.

SFC Developer’s Guide 90


4.2 SFC MODELS

4.2.6.2 Design and Implementation


The application consists of three components: SimulatedService publisher, SimulatedRecord publisher
and a program main. The SimulatedService publisher may be replaced by the
FullCacheSimulatedService publisher for cases where records need to be pre-loaded onto the system.
The SimulatedService component will register with a publishing service (of type
RTRRTRecordServiceImpl) and create simulated records whenever a new published record is added
into the publishing service due to a request from a downstream client components. Note that this class
will only work if the publishing service implementation has the ability to forward requests from
downstream components.

NOTE: This type of sink-driven, or interactive, service model will not work with the TIB implementa-
tion because new requests will not be forwarded to the publisher on an RMDS (RTIC) system.
Rather, requests are always made to an RTIC process on the RMDS network. To work on RTIC, the
simulated service must pre-load records into the publishing service. See the FullCacheSimulated-
Service class in section 4.2.6.5 for details.

Before handling new records, the simulated service makes sure that the FID database is completely
populated because the FID database’s definitions are needed for creating new record fields. To do this,
the service checks the state of the FID database. If the FID database is not in the Complete state, then
the simulated service registers with the FID database to be notified when it is complete or when an
error occurs. Once the FID database is complete, the simulated service may handle requests and
populate records with fields.
The SimulatedRecord provides an initial set of fields to the given published record
(RTRRTRecordImpl) and subsequent state and data changes and events. The state and data changes
occur automatically in each SimulatedRecord based on random time intervals. The data provided to
the published record is hard-coded into the SimulatedRecord, so the record can be populated as soon
as the request for the new symbol is received.
The simulated record will produce many of the possible state and data change events that a record
can transition through as well as a variety of event combinations. In this respect, the SimulatedRecord
represents an interesting test of the ability of the downstream components to handle various events
that may rarely occur on live systems.

SFC Developer’s Guide 91


4.2 SFC MODELS

4.2.6.3 SimulatedService Class Declaration


This section contains the contents of a header file (simsrvc.h) which declares the class
SimulatedService as designed in section 4.2.6.2. Note that the class inherits from
RTRRTRecordServiceImplClient so the processNewRecord() method can be called whenever a new
record is requested by a downstream client component.
#ifndef _simsrvc_h
#define _simsrvc_h

#include "rtr/rtrsvimp.h"
#include "rtr/logevnt.h"
#include "rtr/objid.h"

class SimulatedService
: public virtual RTRRTRecordServiceImplClient
public RTRFidDbClient
{
public:
SimulatedService(RTRObjectId& context,
RTRRTRecordServiceImpl& s,
int lowRangeUpdateRate = 3,
int highRangeUpdateRate = 60);

virtual ~SimulatedService();

void processNewRecord(RTRRTRecordServiceImpl&, RTRRTRecordImpl&);

void processFidDbComplete(RTRFidDb&);
void processFidDbError(RTRFidDb&);

protected:
RTRRTRecordServiceImpl& _implService;
RTRObjectId _instanceId;
RTRLogEvent _logEvent;
int _lowRangeUpdateRate;
int _highRangeUpdateRate;
};

#endif

SFC Developer’s Guide 92


4.2 SFC MODELS

4.2.6.4 SimulatedService Class Definition


This section contains the source file which implements the class SimulatedService as declared in the
previous section (in simsrvc.h).
At construction, the simulated service checks to see if the fidDb of the publishing service is complete.
If not, the service registers (as a descendant of RTRFidDbClient) with the FID database so it can be
called back when the FID database becomes complete.
When the FID database is complete, the simulated service initializes the publishing service by
updating its text, setting its state to NotStale and sending a Sync event to downstream components.
The simulated service also registers to receive events from the publishing service.
As a descendant of RTRRTRecordServiceImplClient, the simulated service inherits the
processNewRecord() method. This method will be called by the publishing service whenever a new
record is being requested by a downstream client (like an SSL or TIB consumer application).

NOTE: The processNewRecord() method will only be called if a new record is added to the publish-
ing service due to demand from downstream client components. Any future requests for a record
that is already populated in the publishing service will be handled by the publishing service; the sim-
ulated service will not be notified.

When the processNewRecord() method is called, the simulator service simply creates a new
instance of SimulatedRecord, providing it with the published record, FID database and high and low
intervals for sending new events to the record (remember, the simulated record sends canned data
and events, so it must determine when to send the events). The simulated record will then handle all
data and state changes associated with that published record.
#include "simsrvc.h"
#include "simrec.h"

SimulatedService::SimulatedService(RTRObjectId& context,
RTRRTRecordServiceImpl& s,
int lr,
int hr)
: _implService(s), _instanceId(context, s.name()),
_lowRangeUpdateRate(lr),
_highRangeUpdateRate(hr)
{
_logEvent.setComponent(_instanceId);

SFC Developer’s Guide 93


4.2 SFC MODELS

if (implService.fidDb().complete())
{
initPubService();
}
else
{
_implService.setText("Waiting for fid db to initialize...");
_implService.indicateInfo();

RTRFidDb*fidDb = (RTRFidDb*)&_implService.fidDb();
fidDb->addClient(*this);
}

void SimulatedService::initPubService()
{
_implService.setText("Ready!");
_implService.setNotStale();
_implService.indicateSync();
_implService.setClient(*this);
}

SimulatedService::~SimulatedService()
{
_implService.unsetClient();
}

void SimulatedService::processNewRecord(RTRRTRecordServiceImpl&,
RTRRTRecordImpl& newRecord)
{
RTRString tmp("Got NewRecord event for record ");
tmp.append(newRecord.symbol());
_logEvent.setText(tmp);
_logEvent.setSeverity(RTRLogSeverity::debug);
_logEvent.log();

// Create a new SimulatedRecord, passing the new RTRRTRecordImpl


// instance that was added to the impl service.
//
SimulatedRecord *simRec = new SimulatedRecord(_instanceId,

SFC Developer’s Guide 94


4.2 SFC MODELS

newRecord,
_implService.fidDb(),
_lowRangeUpdateRate,
_highRangeUpdateRate);
};

void SimulatedService::processFidDbComplete( RTRFidDb& fidDb)


{
// Now that the fid db is complete, activate the service.
initPubService();
}

void SimulatedService::processFidDbError( RTRFidDb& fidDb)


{
_implService.setText(fidDb.errorText());
_implService.indicateInfo();
}

4.2.6.5 FullCacheSimulatedService Class


In cases where the application must run in a source-driven mode, the FullCacheSimulatedService will
be used in place of the SimulatedService class. The only difference between the two classes is that
the FullCacheSimulatedService pre-loads records into the SFC service publisher and disallows
requests from records that are not already cached. Note that the name "FullCache" is another term for
source-driven or non-interactive.
A single extra method load() is called when the service is initialized. This method creates new records
from a list of symbols read in from a configuration parameter. After the records are loaded in, the
service will not accept any requests for different records. The processNewRecord() method shows
how to decline any new records and how to remove those records from the SFC service publisher
cache.
void FullCacheSimulatedService::load()
{

// Get a list of symbols to retrieve. If no configuration


// variable is present, use the default RTRSY.O
//
RTRListOfExternalValue ricList = RTRConfig::configDb().variable(
_classId,

SFC Developer’s Guide 95


4.2 SFC MODELS

_instanceId,
"symbolList",
"RTRSY.O").list(’,’);
RTRRTRecordImpl *_implRecord = 0;
for (ricList.start(); !ricList.off(); ricList.forth())
{
// Check for duplicate symbols.
if (!_implService.hasRTRecordImpl(ricList.item()))
{
// Create a new record in the _implService.
//
_implRecord = &(_implService.newRTRecordImpl( ricList.item() ));

// Create new SimulatedRecord, passing new RTRRTRecordImpl


// instance that was added to the impl service.
//
SimulatedRecord *simRec = new SimulatedRecord(_instanceId,
*_implRecord,
_implService.fidDb(),
_lowRangeUpdateRate,
_highRangeUpdateRate);
if (!simRec->active())
delete simRec;
}
}
}

void FullCacheSimulatedService::processNewRecord(
RTRRTRecordServiceImpl& service,
RTRRTRecordImpl& newRecord)
{
// As a Full Cache service, only the records that were pre-loaded
// into the cache will be made available. By setting the text on
// the newRecord and calling indicateInactive(), we are able to provide
// some reason why the request will not be accepted.
//
// As an alternative, this application component could have not
// become a client of the RTRRTRecordServiceImpl, in which case
// the implService would handle requests for un-cached items. In
// particular, a canned text string ("Item Not Available") would

SFC Developer’s Guide 96


4.2 SFC MODELS

// be returned to the user requesting this item.

// Set the record’s text to something appropriate.


//
newRecord.setText("Cannot satisfy request. Not configured to cache this record");

// Change the record’s state to Inactive.


//
newRecord.setInactive();
newRecord.indicateInactive();

// Remove this new record from the service’s cache.


_implService.removeRTRecordImpl(newRecord.symbol());

// Log a message via the event logger.


RTRString tmp("Rejecting user request for record ");
tmp.append(newRecord.symbol());
_logEvent.setText(tmp);
_logEvent.setSeverity(RTRLogSeverity::debug);
_logEvent.log();
};

4.2.6.6 SimulatedRecord Publisher Class Declaration


This section contains the contents of a header file (simrec.h) which declares the class
SimulatedService as designed in section 4.2.6.2. The class declares several methods that are used to
take the different actions available through the RTRRTRecordImpl interface. This class inherits the
RTRRTRecordImplClient class so it can register with its RTRRTRecordImpl to receive notifications
whenever the record transitions between watched and unwatched.
Note that a static template number variable is declared. This may be used to set up a template number
to be published to all records. This may be required by some downstream client applications.
#ifndef _simrec_h
#define _simrec_h

#include "rtr/rtrecimp.h" // RTRRTRecordImpl


#include "rtr/random.h" // Random number generator
#include "rtr/vardatti.h" // Date/Time class
#include "rtr/timercmd.h" // RTRTimerCmd class
#include "rtr/logevnt.h" // RTRLogEvent

SFC Developer’s Guide 97


4.2 SFC MODELS

#include "rtr/objid.h" // RTRObjectId


#include "rtr/fid_db.h" // RTRFidDb

class SimulatedRecord
: public RTRRTRecordImplClient,
public RTRTimerCmd
{
public:

SimulatedRecord(RTRObjectId& context,
RTRRTRecordImpl& record,
const RTRFidDb& fidDb,
long lowRange,
long highRange);

virtual ~SimulatedRecord();

// Inherited From RTRTimerCmd


void processTimerEvent();

void setTimer();

// Inherited From RTRRTRecordImplClient


void processHasEventClient(RTRRTRecordImpl&);

void processNotHasEventClient(RTRRTRecordImpl&);

// Update event propagation


void sendUpdate();

void sendCorrection();

void sendClosingRun();

// State change event propagation


void sendInfo();

void sendStale();

void sendNotStale();

SFC Developer’s Guide 98


4.2 SFC MODELS

void sendResync();

// Utility
void updateFields();

void initializeFields(const RTRFidDb&);

protected:
RTRRandomNumberGenerator _randomValue;
RTRRTFieldUpdateList _updList;
RTRRTRecordImpl& _record;
RTRObjectId _instanceId;
RTRLogEvent _logEvent;
RTRVariableDateTime _dateTime;
int _counter;
int _bidVal;
int _tradeVal;
int _askVal;
int _acvolVal;

};

#endif

4.2.6.7 SimulatedRecord Class Definition


This section contains the source file which implements the class SimulatedRecord as declared in the
previous section (in simrec.h).
At construction, the simulated record initializes the given published record by adding fields to the
published record, setting the descriptive text of the published record, changing the state to NotStale
and then sending a RecordSync event to downstream components. The simulated record also
registers with the published record to receive watched/not-watched events.
The initializeFields() method shows how to create each of the defined field types, initialize the data
for the field and add the field to the published record. The updateFields() method shows how to
update fields in the published record.
A timer is set in the constructor to determine when to send different events. The processTimerEvent()
method is called when the timer expires. The various helper methods are then used to update the data

SFC Developer’s Guide 99


4.2 SFC MODELS

fields and to modify the state of the record. Associated events are sent to downstream client
components through the RTRRTRecordImpl interface methods. After taking the appropriate action, the
simulated record gets the next random time interval (between the high and low ranges) and activates
the timer again. This continues for the life of the simulated record.
As a registered RTRRTRecordImplClient, the simulated record prints out a message whenever a
transition occurs between having and not having downstream event clients.
The simulated record will continue running indefinitely.
#include "simrec.h"
#include "rtr/rtstrhsh.h"

SimulatedRecord::SimulatedRecord(RTRObjectId& context,
RTRRTRecordImpl& record,
const RTRFidDb& fidDb,
long lowRange,
long highRange)
: _record(record), _updList(record),
_bidVal(1), _askVal(3), _tradeVal(2),
_counter(1), _instanceId(context,record.symbol()),
_randomValue((int)strHashFunction(
record.symbol()),
highRange, lowRange)
{
_logEvent.setComponent(_instanceId);

_record.addClient(*this);

// Create and add fields to the record impl.


initializeFields(fidDb);

_record.setText("Ready.");
_record.setNotStale();
_record.indicateSync();

setTimer();
activate();
}

SimulatedRecord::~SimulatedRecord()

SFC Developer’s Guide 100


4.2 SFC MODELS

{
_record.dropClient(*this);

// Clean up memory allocated by this record.


_record.deleteAllFields();

// From RTRTimerCmd
void SimulatedRecord::processTimerEvent()
{
// Do different kinds of data and state
// events periodically.
_counter++;
if (!(_counter % 4))
{
if (_record.stale())
sendInfo();
else
sendStale();
}
else if (!(_counter % 5))
{
sendResync();
}
else if (!(_counter % 3))
{
sendCorrection();
}
else if (!(_counter % 120))
{
sendClosingRun();
}
else
sendUpdate();

// Wait some random amount of time before executing


// the next event. The time interval is between the
// lowRange and highRange values provided at
// construction.

SFC Developer’s Guide 101


4.2 SFC MODELS

setTimer();
activate();
}

void SimulatedRecord::setTimer()
{
_randomValue.getNext();
setTimerOffset(_randomValue, 0);
}

// From RTRRTRecordImplClient
void SimulatedRecord::processHasEventClient(RTRRTRecordImpl&)
{
_logEvent.setText("Users are now monitoring this record.");
_logEvent.setSeverity(RTRLogSeverity::debug);
_logEvent.log();
}

void SimulatedRecord::processNotHasEventClient(RTRRTRecordImpl&)
{
_logEvent.setText("Users are no longer monitoring this record.");
_logEvent.setSeverity(RTRLogSeverity::debug);
_logEvent.log();
}

void SimulatedRecord::updateFields()
{
static RTRString val;
RTRRTField *fld = 0;
_tradeVal++;
_bidVal++;
_askVal++;
_acvolVal += 100;

_updList.reinitialize(_record);

// Update the TRDPRC_1 (fid 6) field. Note the


// use of the RTRRTRecordImpl and RTRRTFieldUpdateList
// methods that take fid numbers for parameters.
val.clear();

SFC Developer’s Guide 102


4.2 SFC MODELS

fld = _record.field(6);
if (fld)
{
val.append(_tradeVal);
fld->set(val,val.count());
fld->indicateFieldUpdated();
_updList.putFieldByFid(6);
}

// Update the BID (fid 22) field. Note the


// use of the RTRRTRecordImpl and RTRRTFieldUpdateList
// methods that take the fid names for parameters.
val.clear();
fld = _record.fieldByName("BID");
if (fld)
{
val.append(_bidVal);
fld->set(val,val.count());
fld->indicateFieldUpdated();
_updList.putFieldByName("BID");
}

val.clear();
fld = _record.fieldByName("ASK");
if (fld)
{
val.append(_askVal);
fld->set(val,val.count());
fld->indicateFieldUpdated();
_updList.putField(*fld);
}

val.clear();
fld = _record.fieldByName("ACVOL_1");
if (fld)
{
val.append(_acvolVal);
fld->set(val,val.count());
fld->indicateFieldUpdated();
_updList.putField(*fld);

SFC Developer’s Guide 103


4.2 SFC MODELS

val.clear();
fld = _record.fieldByName("TRDTIM_1");
if (fld)
{
_dateTime.setToSystemTime();
val.append(_dateTime.hours());
val.append(":");
val.append(_dateTime.minutes());
val.append(":");
val.append(_dateTime.seconds());
fld->set(val,val.count());
fld->indicateFieldUpdated();
_updList.putField(*fld);
}
}

void SimulatedRecord::sendUpdate()
{
_record.indicateUpdateTick();
updateFields();
_record.indicateUpdateComplete(_updList);
}

void SimulatedRecord::sendCorrection()
{
_record.indicateCorrectionTick();
updateFields();
_record.indicateUpdateComplete(_updList);
}

void SimulatedRecord::sendClosingRun()
{
// Update the record and indicate.
//
_record.indicateCloseTick();
updateFields();
_record.indicateUpdateComplete(_updList);
}

SFC Developer’s Guide 104


4.2 SFC MODELS

void SimulatedRecord::sendInfo()
{
// Notify info
_record.setText("Informational message...");
_record.indicateInfo();
}

void SimulatedRecord::sendStale()
{
// Notify info
_record.setText("GOING STALE NOW");
_record.setStale();
_record.indicateStale();
}

void SimulatedRecord::sendNotStale()
{
_record.setText("OK NOW");
_record.setNotStale();
_record.indicateNotStale();
}

void SimulatedRecord::sendResync()
{
_record.setText("Resyncronized");
if (_record.stale())
_record.setNotStale();
else
_record.setStale();
_record.indicateResync();
updateFields();
_record.indicateResyncComplete(_updList);
}

void SimulatedRecord::initializeFields(const RTRFidDb& fidDb)


{
const RTRFidDefinition *fidDef = 0;
RTRRTField *fld = 0;
char *farea = 0;

SFC Developer’s Guide 105


4.2 SFC MODELS

// Add DSPLY_NAME field using this record’s symbol as


// the field’s value. This is an example of creating
// an Alphanumeric field.
//
// NOTE: Could also use fidDb.defByFid(3) here.
//
fidDef = fidDb.defByName("DSPLY_NAME");
if (fidDef)
{
// NOTE: Always add 1 character for end-of-field delimiter.
//
farea = new char[fidDef->length() + 1];
fld = new RTRRTAlphanumericField(*fidDef, farea, 0);
fld->set(_record.symbol(), _record.symbol().count());
_record.putField(*fld);
}

// Add TRDPRC_1 field - a Price field


//
// NOTE: Could also use fidDb.defByName("TRDPRC_1") here.
//
fidDef = fidDb.defByFid(6);
if (fidDef)
{
farea = new char[fidDef->length() + 1];
fld = new RTRRTPriceField(*fidDef, farea, 0);
fld->set("2", 1);
_record.putField(*fld);
}

// Add ACVOL_1 field - an Integer field


//
fidDef = fidDb.defByName("ACVOL_1");
if (fidDef)
{
farea = new char[fidDef->length() + 1];
fld = new RTRRTIntegerField(*fidDef, farea, 0);
fld->set("200", 1);
_record.putField(*fld);

SFC Developer’s Guide 106


4.2 SFC MODELS

// Add TRADE_DATE field - a Date field


//
fidDef = fidDb.defByName("TRADE_DATE");
if (fidDef)
{
farea = new char[fidDef->length() + 1];
fld = new RTRRTDateTimeField(*fidDef, farea, 0);

// NOTE: Date format is "MM/DD/YY"


//
_dateTime.setToSystemTime();
RTRString tmp;
tmp.append(_dateTime.monthNumber());
tmp.append("/");
tmp.append(_dateTime.dayOfMonth());
tmp.append("/");
tmp.append(_dateTime.year());

fld->set(tmp, tmp.count());
_record.putField(*fld);
}

// Add TRDTIM_1 field - a Time field


//
fidDef = fidDb.defByName("TRDTIM_1");
if (fidDef)
{
farea = new char[fidDef->length() + 1];
fld = new RTRRTDateTimeField(*fidDef, farea, 0);

// NOTE: Time format is "HH:MM:SS" or "HH:MM"


//
_dateTime.setToSystemTime();
RTRString tmp;
tmp.append(_dateTime.hours());
tmp.append(":");
tmp.append(_dateTime.minutes());

SFC Developer’s Guide 107


4.2 SFC MODELS

fld->set(tmp, tmp.count());
_record.putField(*fld);
}

// Add RDN_EXCHID field - an Enumerated field


//
fidDef = fidDb.defByName("RDN_EXCHID");
if (fidDef)
{
farea = new char[fidDef->length() + 1];
fld = new RTRRTEnumeratedField(*fidDef, farea, 0,
*fidDb.enumTableByName("RDN_EXCHID"));
fld->set("NYS", 3);
_record.putField(*fld);
}

// Add TRDPRC_2 field


//
fidDef = fidDb.defByName("TRDPRC_2");
if (fidDef)
{
farea = new char[fidDef->length() + 1];
fld = new RTRRTPriceField(*fidDef, farea, 0);
fld->set("0", 1);
_record.putField(*fld);
}

// Add TRDPRC_3 field


//
fidDef = fidDb.defByName("TRDPRC_3");
if (fidDef)
{
farea = new char[fidDef->length() + 1];
fld = new RTRRTPriceField(*fidDef, farea, 0);
fld->set("0", 1);
_record.putField(*fld);
}

// Add TRDPRC_4 field


//

SFC Developer’s Guide 108


4.2 SFC MODELS

fidDef = fidDb.defByName("TRDPRC_4");
if (fidDef)
{
farea = new char[fidDef->length() + 1];
fld = new RTRRTPriceField(*fidDef, farea, 0);
fld->set("0", 1);
_record.putField(*fld);
}

// Add TRDPRC_5 field


//
fidDef = fidDb.defByName("TRDPRC_5");
if (fidDef)
{
farea = new char[fidDef->length() + 1];
fld = new RTRRTPriceField(*fidDef, farea, 0);
fld->set("0", 1);
_record.putField(*fld);
}

// Add BID field


//
fidDef = fidDb.defByName("BID");
if (fidDef)
{
farea = new char[fidDef->length() + 1];
fld = new RTRRTPriceField(*fidDef, farea, 0);
fld->set("1", 1);
_record.putField(*fld);
}

// Add BID_1 field


//
fidDef = fidDb.defByName("BID_1");
if (fidDef)
{
farea = new char[fidDef->length() + 1];
fld = new RTRRTPriceField(*fidDef, farea, 0);
fld->set("0", 1);
_record.putField(*fld);

SFC Developer’s Guide 109


4.2 SFC MODELS

// Add BID_2 field


//
fidDef = fidDb.defByName("BID_2");
if (fidDef)
{
farea = new char[fidDef->length() + 1];
fld = new RTRRTPriceField(*fidDef, farea, 0);
fld->set("0", 1);
_record.putField(*fld);
}

// Add ASK field


//
fidDef = fidDb.defByName("ASK");
if (fidDef)
{
farea = new char[fidDef->length() + 1];
fld = new RTRRTPriceField(*fidDef, farea, 0);
fld->set("3", 1);
_record.putField(*fld);
}

// Add ASK_1 field


//
fidDef = fidDb.defByName("ASK_1");
if (fidDef)
{
farea = new char[fidDef->length() + 1];
fld = new RTRRTPriceField(*fidDef, farea, 0);
fld->set("0", 1);
_record.putField(*fld);
}

// Add ASK_2 field


//
fidDef = fidDb.defByName("ASK_2");
if (fidDef)
{

SFC Developer’s Guide 110


4.2 SFC MODELS

farea = new char[fidDef->length() + 1];


fld = new RTRRTPriceField(*fidDef, farea, 0);
fld->set("0", 1);
_record.putField(*fld);
}
}

4.2.6.8 Creating an Application


The preceding sections showed how to design, declare and implement simulator publishing
components that can publish to any system. This section shows how to include the new classes in an
application. The Simulator program that is provided in the product distribution has the ability to run on
either RMDS or Triarch systems or strictly in-process. It also can run in sink-driven (interactive) or
source-driven (non-interactive) modes.
This section will show how to create and combine the right components to accomplish each of these
configurations. The code snippets shown in this section have been taken from the simulator.C source
file and reorganized based on the implementation that is being used - SSL, TIB or in-process.
There actually are not many differences required in the code to run with the different service
implementations. The basic sequence of events used to create an application is:
1. Include required header files.
2. Create any required utility objects, like the application identifier, configuration database and
event logger. These need to be created first because other components will use them.
3. Create the specific type of SFC publishing service that is required. This could be one of
the following publishing service types: RTRRTFieldToSSLRecordService,
RTRRTFieldToTIBRecordService or RTRRTFieldToFieldRecordService.
4. Create the specific type of simulated service that is required. This could be either the
SimulatorService for sink-driven, interactive mode or the FullCacheSimulatedService for
source-driven, non-interactive mode. The simulated service will be given the SFC publishing
service created in step 2.
5. Create record display components, if necessary. In this application, this is only necessary
for displaying data from a RTRRTFieldToFieldRecordService. In that case, the dat aif printed to
stdout.
6. Initialize the main-loop notifier to start handling I/O and timer events.

SFC Developer’s Guide 111


4.2 SFC MODELS

7. Clean-up when the program is exiting.

Application code for running SimulatedService on SSL


The following code includes the header files needed by most SFC application, independent of any
downstream infrastructure that is being used:
#include <iostream.h>
#include "rtr/selectni.h"// RTRSelectNotifier
#include "rtr/rtxfdb.h"// RTRXFileDb, RTRConfig
#include "rtr/dfltlog.h"// RTRDefaultLogger
#include "rtr/cmdline.h"// RTRCmdLine
These headers are needed to publish to a Triarch system:
#include "rtr/fldtossl.h"// RTRRTFieldToSSLRecordService
#include "rtr/ufdb.h" // RTRFileFidDb
This header is needed to publish simulated data in a sink-driven mode.
#include "simsrvc.h" // SimulatedService
This code creates utility objects that allow SFC components to read configuration information and log
events to log files and stderr. The logger makes use of the configDb, so the configDb is instantiated
first:
RTRObjectId appId("Simulator");
// Initialize the configuration database
configDb = new RTRXFileDb(clConfigPath.stringValue());
if (configDb->error())
{
cerr << "Config error: " << configDb->errorText() << endl;
cleanup(-2, argv[0]);
}
RTRConfig::setConfigDb(*configDb);

RTRDefaultLogger logger(appId, "logger");


This code creates the publishing service and the simulated service that will provide data to the
publishing service. Note that the RTRRTFieldToSSLRecordService has several different constructors
that may be used. This particular one takes a FID database at construction, but uses default values to
create the well-known port that downstream Triarch components and user applications will connect to:

SFC Developer’s Guide 112


4.2 SFC MODELS

initSSLFidDb();
pubService = new RTRRTFieldToSSLRecordService(appId,
pubServiceName,
*sslfdb);
simService = new SimulatedService(appId, *pubService);
This code creates a Triarch FID database which is loaded from a disk file:
void initSSLFidDb()
{
if (!sslfdb)
{
sslfdb = new RTRFileFidDb (appId, "fidDb");
((RTRFileFidDb *) sslfdb)->load();
if (sslfdb->error())
{
cout<< "FidDb error: " << sslfdb->errorText() <<endl;
cleanup(-2);
}
}
}
This code initializes the notifier to run and cleans up resources after the notification loop exits. Note
that in this example, the system select() version of the notifier is being used. Each implementation of
notifier will have a different way to start the main loop. See section 4.8.3 for details.
Note that all cleanup must be done in the opposite order of creation to ensure that resources are
properly freed and objects do not reference components that have already been deleted:
RTRSelectNotifier::run();

delete simService
delete pubService;
delete sslfdb;
delete logger;
delete configDb;
return 0;

SFC Developer’s Guide 113


4.2 SFC MODELS

Application code for running FullCacheSimulatedService on RMDS with a TIBCO


Rendezvous Distribution Layer
The following code includes the header files needed by most SFC application, independent of any
downstream infrastructure that is being used:
#include <iostream.h>
#include "rtr/selectni.h"// RTRSelectNotifier
#include "rtr/rtxfdb.h"// RTRXFileDb, RTRConfig
#include "rtr/dfltlog.h"// RTRDefaultLogger
#include "rtr/cmdline.h"// RTRCmdLine
These headers are needed to publish to a TIB system:
#include "rtr/tconnect.h"// RTRTIBConnection
#include "rtr/fldtotib.h"// RTRRTFieldToTIBRecordService
#include "rtr/tfdb.h" // RTRTIBFidDb
This header is needed to publish simulated data in a source-driven mode. Note that the
FullCacheSimulatedService is being used on the RMDS network with a TIBCO Rendezvous
Distribution Layer because this simulated service pre-loads the cache with records. This is required as
the TIB publishing service implementation will not provide notifications when users on the RMDS
network with a TIBCO Rendezvous Distribution Layer access a new record, so the records need to be
pre-loaded.
#include "fcsimsrvc.h" // FullCacheSimulatedService
This code creates utility objects that allow SFC components to read configuration information and log
events to log files and stderr. The logger makes use of the configDb, so the configDb is instantiated
first:
RTRObjectId appId("Simulator");
// Initialize the configuration database
configDb = new RTRXFileDb(clConfigPath.stringValue());
if (configDb->error())
{
cerr << "Config error: " << configDb->errorText() << endl;
cleanup(-2, argv[0]);
}
RTRConfig::setConfigDb(*configDb);

RTRDefaultLogger *logger = new RTRDefaultLogger(appId, "logger");

SFC Developer’s Guide 114


4.2 SFC MODELS

This code creates the TIB publishing service and the simulated service that will provide data to the
publishing service. Note that the RTRRTFieldToTIBRecordService has several different constructors
that may be used. This particular constructor takes a context ID, name of the service and a connection
at construction. The connection handles connectivity to RTIC via the RVD. The publishing service will
automatically download the data dictionary (FID database).
connection = new RTRTIBConnection(appId,
"tibconnection",
servicePort,
network,
daemon);
connection->connect();

RTRRTFieldToTIBRecordService *pubService =
new RTRRTFieldToTIBRecordService(appId,
pubServiceName,
*connection);
simService = new FullCacheSimulatedService(appId, *pubService);
This code initializes the notifier to run and cleans up resources after the notification loop exits. Note
that in this example, the system select() version of the notifier is being used. Each implementation of
notifier will have a different way to start the main loop. See section 4.8.3 for details.
Note that all cleanup must be done in the opposite order of creation to ensure that resources are
properly freed and objects do not reference components that have already been deleted:
RTRSelectNotifier::run();

delete simService
delete pubService;
delete connection;
delete logger;
delete configDb;
return 0;

Application code for running SimulatedService in-process


The following code includes the header files needed by most SFC applications, independent of any
downstream infrastructure that is being used:
#include <iostream.h>
#include "rtr/selectni.h"// RTRSelectNotifier

SFC Developer’s Guide 115


4.2 SFC MODELS

#include "rtr/rtxfdb.h"// RTRXFileDb, RTRConfig


#include "rtr/dfltlog.h"// RTRDefaultLogger
#include "rtr/cmdline.h"// RTRCmdLine
This header is needed to publish simulated data in a sink-driven mode
#include "simsrvc.h" // SimulatedService
This header are needed to publish in-process to other SFC consumer components:
#include "rtr/fldtofld.h"// RTRRTFieldToFieldRecordService
This header is needed to display SFC data published within the process:
#include "tickclient.h" // TickerClient
typedef TickerClient *TickerClientPtr;
This header is needed to publish simulated data in a source-driven mode. Note that the
FullCacheSimulatedService is being used on the RMDS network with a TIBCO Rendezvous
Distribution Layer because this simulated service pre-loads the cache with records. This is required as
the TIB publishing service implementation will not provide notifications when users on the RMDS
network with a TIBCO Rendezvous Distribution Layer access a new record, so the records need to be
pre-loaded.
#include "fcsimsrvc.h" // FullCacheSimulatedService
This code creates utility objects that allow SFC components to read configuration information and log
events to log files and stderr. The logger makes use of the configDb, so the configDb is instantiated
first:
RTRObjectId appId("Simulator");
// Initialize the configuration database
configDb = new RTRXFileDb(clConfigPath.stringValue());
if (configDb->error())
{
cerr << "Config error: " << configDb->errorText() << endl;
cleanup(-2, argv[0]);
}
RTRConfig::setConfigDb(*configDb);

RTRDefaultLogger logger(appId, "logger");


This code creates an in-process publishing service and the simulated service that will provide data to
the publishing service. The field-to-field publishing service constructor takes a context ID, the name of

SFC Developer’s Guide 116


4.2 SFC MODELS

the service and a FID database at construction. The publishing service is then given to a number of
SFC consumer clients that display record data to stdout.
// RTFieldToFieldService is a RTRecordServiceImpl
// and a RTRecordService.
initSSLFidDb();
RTRRTFieldToFieldRecordService *pubService =
new RTRRTFieldToFieldRecordService(pubServiceName,
*sslfdb);
simService = new SimulatedService(appId,
*pubService);
createFieldClients(*pubService);
This code initializes several display components that obtain data from an RTRRTRecordService and
display it to stdout. Each TickerClient component watches a single record and displays various fields
from the record to stdout. Note that the service passed into the createFieldClients() method takes a
type of RTRRTRecordService. Since the RTRRTFieldToFieldRecordService implements the
RTRRTRecordService (consumer) interface in addition to the RTRRTRecordServiceImpl (publishing)
interface, the publishing service is passed directly to the createFieldClients() method.
void createFieldClients(RTRRTRecordService &service)
{
RTRListOfExternalValue ricList = RTRConfig::configDb().variable(
appId, "Simulator", "symbolList", "RTRSY.O").list(’,’);
clients = new TickerClientPtr [ricList.count()];
int i = 0;
for (ricList.start(); !ricList.off(); ricList.forth(), i++)
clients[i] = new TickerClient(service, ricList.item());
}
This code initializes the notifier to run and cleans up resources after the notification loop exits. Note
that in this example, the system select() version of the notifier is being used. Each implementation of
notifier will have a different way to start the main loop. See section 4.8.3 for details.
Note that all cleanup must be done in the opposite order of creation to ensure that resources are
properly freed and objects do not reference components that have already been deleted:
RTRSelectNotifier::run();

delete clients[];
delete simService
delete pubService;

SFC Developer’s Guide 117


4.2 SFC MODELS

delete logger;
delete configDb;
return 0;

4.2.7 Gateway Example


Another example program available in the product distribution is the Gateway program. This section
will provide some helpful hints for writing gateway applications that source data from one market-data
system via SFC and publish into another market-data system. Many of the basic algorithms used to
create records, handle SFC publishing service events, publish record data and events remain the
same in this program (and in all programs). The main difference from the Simulator program is that the
data and events are obtained from a subscription service or record which works asynchronously.
This sort of application can be used to bridge two different market data systems or to create a new
service that implements value-added processing to existing SFC record data. This program acts as a
bridge, but can easily be modified to do value-added processing. This is how some of the other
example programs provided in the product distribution have been built. Namely, the Injector program
adds a calculated mid-price to each record and the Aggregator provides record updates at a specified
rate. Each of these programs uses the basic structure of this program.
Note that the application main() has been omitted. See the source file for the Gateway program for
details.

4.2.7.1 Requirements
The application must respond to requests from downstream clients for live record data and subsequent
update and state change notifications that are obtained from a different upstream market data system.
No translation of the data is made; it is simply published straight to the SFC publishing service.
The main purpose of the program is to show how to set up a gateway publishing service and how to
ensure that your application can be made portable across multiple market data systems. This
application also shows how an application can respond to new record requests in an asynchronous
fashion and apply data updates and state changes in an asynchronous fashion.
This application can be used as a starting point for gateway style applications.

SFC Developer’s Guide 118


4.2 SFC MODELS

4.2.7.2 Design and Implementation


The application consists of five components: GatewayService publisher, SinkGatewayService,
SourceGatewayService, GatewayRecord publisher and a program main. The GatewayService is the
base class for the SinkDrivenGatewayService and SourceDrivenGatewayService.
The GatewayService acts as a proxy for an upstream SFC-based service and provides a
GatewayRecord cache. All state change events that occur in an upstream SFC service will be
immediately reflected in the downstream SFC publishing service. See section 4.2.7.3 and 4.2.7.4 for
details.
The SinkDrivenGatewayService is a gateway service implementation that accepts requests for new
published records from downstream client components (e.g. Triarch Source Distributor or user
applications) and creates new GatewayRecords to supply data and events to the new published
records. It also inherits all the functionality of the GatewayService. See section 4.2.7.5 and 4.2.7.6 for
details.
The SourceDrivenGatewayService is a gateway service implementation that determines the contents
of its cache via a configured list of symbols. This service will not accept requests for new published
records; it will only publish the records found in the configured list. This service also inherits all the
functionality of the GatewayService. See section 4.2.7.7 and 4.2.7.8 for details.
GatewayRecord is in charge of handling all data and state change events from an upstream SFC-
based record and publishing those changes back out to downstream client components through an
SFC published record. The GatewayRecord acts as a proxy for the upstream SFC-based record. See
section 4.2.7.9 and 4.2.7.10 for details.

4.2.7.3 GatewayService Class Declaration


This section contains the contents of a header file (gatesvc.h) which declares the class
GatewayService as designed in section 4.2.7.2. Note that the class inherits from RTRMDServiceClient
so it can receive events from an upstream SFC service of type RTRRTRecordService.
#ifndef _gatesvc_h
#define _gatesvc_h

#include "rtr/rtrecsrv.h" // RTRMDService


#include "rtr/rtrsvimp.h" // RTRRTRecordServiceImpl
#include "rtr/objid.h"// RTRObjectId
#include "rtr/logevnt.h" // RTRLogEvent

SFC Developer’s Guide 119


4.2 SFC MODELS

#include "rtr/rtllist.h"// RTRLinkedList


#include "gaterec.h"

class GatewayService
: public RTRMDServiceClient
{
public:
// Constructor
GatewayService(RTRObjectId& context,
RTRRTRecordServiceImpl& implService,
RTRRTRecordService& gateService);

// Destructor
virtual ~GatewayService();

// Identification
const char *name();

// Service event propogation (From RTRMDServiceClient)


virtual void processServiceAlert(RTRMDService&) {};
// A new alert is available from service s
// (via method lastAlert()).

virtual void processServiceTimestamp(RTRMDService&) {};


// A new timestamp is available from service s
// (via method lastTimestamp()).

virtual void processServiceInfo(RTRMDService& gateService);


// A new explanatory message is available from service s
// (via method text()).

virtual void processServiceHeadline(RTRMDService& ) {};


// A new headline is available from service s
// (via method lastHeadline()).

// Service "state" event propogation (From RTRMDServiceClient)


virtual void processServiceSync(RTRMDService& gateService);

virtual void processServiceStale(RTRMDService& gateService);

SFC Developer’s Guide 120


4.2 SFC MODELS

virtual void processServiceInactive(RTRMDService& gateService);

// Access
RTRBOOL hasRecord(const RTRString& symbol);
// Is the gateway record associated with symbol currently
// cached?

void addRecord(GatewayRecord *gateRec);


// Add the given record to the gateway service’s cache.
// REQUIRE: !hasRecord(symbol)

void removeRecord(const RTRString& symbol);


// Remove the gateway record associated with symbol from
// the gateway service’s cache.

protected:
RTRRTRecordService& _gateService;
RTRRTRecordServiceImpl& _implService;
RTRLinkedList<GatewayRecord> _cache;
RTRObjectId _instanceId;
RTRObjectId _classId;
RTRLogEvent _logEvent;
};

#endif

4.2.7.4 GatewayService Class Definition


This section contains the source file which implements the class GatewayService as declared in the
previous section (in gatesvc.h).
At construction, the gateway service is given two other services: an RTRRTRecordService
(subscription service) from which to access data and state and a RTRRTRecordServiceImpl
(publishing service) that is used to publish the same data and state information. The publishing service
is initialized to the text() of the subscription service and a state of Stale. Further initialization activities
will be implemented by descendants of this class.
As a descendant of RTRMDServiceClient, the gateway service inherits methods that will be called
whenever the state of the subscription service has changed. In the constructor, the gateway service

SFC Developer’s Guide 121


4.2 SFC MODELS

registers with the subscription service to receive these events. Each of the methods inherited from
RTRMDServiceClient are implemented to on-pass the event and gateway service text to the publishing
service.
There are several methods that are used to create, store and destroy all GatewayRecord instances
created in this service. This cache of gateway records is needed to allow for proper clean-up when the
gateway service is destructed.
The destructor for this class will basically undo all the previous actions. Specifically, the publishing
service is sent an Inactive event, all the gateway records are destroyed and the gateway service
deregisters from the subscription service.

#include "gatesvc.h" // GatewayService


#include "gaterec.h" // GatewayRecord

GatewayService::GatewayService(
RTRObjectId& context,
RTRRTRecordServiceImpl& implService,
RTRRTRecordService& gateService)
: _implService(implService), _gateService(gateService),
_instanceId(context, gateService.name()),
_classId("GatewayService")
{
_logEvent.setComponent(_instanceId);

_gateService.addClient(*this);
_implService.setText(gateService.text());
_implService.setStale();
};

GatewayService::~GatewayService()
{
if (_gateService.hasClient(*this))
_gateService.dropClient(*this);

_implService.setText("Service unavailable.");
_implService.setInactive();
_implService.indicateInactive();

for (_cache.start(); !_cache.off(); _cache.start())

SFC Developer’s Guide 122


4.2 SFC MODELS

{
GatewayRecord *gateRec = _cache.item();
delete gateRec;
}
};

const char *GatewayService::name()


{
return _implService.name();
}

RTRBOOL GatewayService::hasRecord(const RTRString& symbol)


{
RTRLinkedList<GatewayRecord>& list = _cache;
for (list.start(); !list.off(); list.forth())
{
if (list.item()->symbol() == symbol)
break;
}
if (list.off())
return RTRFALSE;
else
return RTRTRUE;
}

void GatewayService::removeRecord(const RTRString& symbol)


{
for (_cache.start(); !_cache.off(); _cache.forth())
{
if (_cache.item()->symbol() == symbol)
{
_cache.remove();
break;
}
}
}

void GatewayService::addRecord(GatewayRecord *gateRec)


{
RTPRECONDITION( !hasRecord(gateRec->symbol()) );

SFC Developer’s Guide 123


4.2 SFC MODELS

_cache.extend(gateRec);
}

void GatewayService::processServiceInfo(RTRMDService& gateService)


// A new explanatory message is available from service s
// (via method text()).
{
_implService.setText(gateService.text());
_implService.indicateInfo();
};

void GatewayService::processServiceSync(RTRMDService& gateService)


{
_implService.setNotStale();
_implService.setText(gateService.text());
_implService.indicateSync();
};

void GatewayService::processServiceStale(RTRMDService& gateService)


{
_implService.setStale();
_implService.setText(gateService.text());
_implService.indicateStale();
};

void GatewayService::processServiceInactive(RTRMDService& gateService)


{
_implService.setInactive();
_implService.setText(gateService.text());
_implService.indicateInactive();
_implService.unsetClient();
_gateService.dropClient(*this);
delete this;
};

SFC Developer’s Guide 124


4.2 SFC MODELS

4.2.7.5 SinkDrivenGatewayService Class Declaration


This section contains the contents of a header file (sinkgates.h) which declares the class
SinkDrivenGatewayService as designed in section 4.2.7.2. Note that the class inherits from
RTRRTRecordServiceImplClient so it can receive events from the publishing service. It also inherits all
the capabilities of the GatewayService.
#ifndef _sinkgates_h
#define _sinkgates_h

#include "gatesvc.h"

class SinkDrivenGatewayService
: public GatewayService,
public virtual RTRRTRecordServiceImplClient
{
public:
// Constructor
SinkDrivenGatewayService(RTRObjectId& context,
RTRRTRecordServiceImpl& implService,
RTRRTRecordService& gateService);

// Destructor
virtual ~SinkDrivenGatewayService();

// Service impl notifications (From RTRRTRecordServiceImplClient)


void processNewRecord(RTRRTRecordServiceImpl&,
RTRRTRecordImpl&);

};

#endif

4.2.7.6 SinkDrivenGatewayService Class Definition


This section contains the source file which implements the class SinkDrivenGatewayService as
declared in the previous section (in sinkgates.h).
As a descendant of RTRRTRecordServiceImplClient, the SinkDrivenGatewayService (gateway
service) adds the ability to receive notifications from a RTRTRecordServiceImpl (publishing service)
whenever a new record has been added to the service’s cache. These notifications are generated by

SFC Developer’s Guide 125


4.2 SFC MODELS

the publishing service whenever a user of that service requests data for a record that is not currently in
the service’s cache. The term "sink driven" is used to describe a service that has the ability to receive
record requests interactively from the publishing service.
It is the responsibility of this component to take action whenever a processNewRecord() event
occurs. In this implementation, a new GatewayRecord instance is created to supply data and state
information to the given published record. The data and state information is obtained from a different
record service, the subscription service which is given to the new GatewayRecord instance at
construction.
As a descendant of GatewayService, this class inherits the ability to handle service level events from
the subscription service and to cache GatewayRecords.
At construction, the SinkDrivenGatewayService is given two other services: an RTRRTRecordService
(subscription service) from which to access data and state and a RTRRTRecordServiceImpl
(publishing service) that is used to publish the same data and state information. If the subscription
service is in the NotStale state, then the publishing service is also initialized to the NotState state and a
ServiceSync event is sent to all downstream client components. If the subscription service is Stale,
then this class waits until the subscription service transitions to NotStale (as indicated when the
GatewayService::processServiceSync() event is called by the subscription service).
The processNewRecord() method is implemented to create a new GatewayRecord instance for the
given published record and to log the event through the SFC logger. The GatewayRecord constructor
takes an instance of RTRRTRecord (subscription record) that is obtained from the subscription
service. This is the record that the gateway record will be publishing information from. Note that the
GatewayRecord will add itself to the cache of this gateway service.
#include "sinkgates.h" // SinkDrivenGatewayService

SinkDrivenGatewayService::SinkDrivenGatewayService(
RTRObjectId& context,
RTRRTRecordServiceImpl& implService,
RTRRTRecordService& gateService)
: GatewayService(context, implService, gateService)
{
_implService.setClient(*this);
if (!_gateService.stale())
{
_implService.setText(_gateService.text());
_implService.setNotStale();
_implService.indicateSync();

SFC Developer’s Guide 126


4.2 SFC MODELS

}
};

SinkDrivenGatewayService::~SinkDrivenGatewayService()
{
_implService.unsetClient();
};

void SinkDrivenGatewayService::processNewRecord(
RTRRTRecordServiceImpl&,
RTRRTRecordImpl& newRecord)
{
RTRString tmp("Got NewRecord event for new record ");
tmp.append(newRecord.symbol());

_logEvent.setText(tmp);
_logEvent.setSeverity(RTRLogSeverity::debug);
_logEvent.log();

RTRRTRecord& _sinkRecord = _gateService.rtRecord(newRecord.symbol());

GatewayRecord *gateRecord = new GatewayRecord(_instanceId,


_sinkRecord,
newRecord,
*this);
if (!gateRecord->active())
delete gateRecord;
};

4.2.7.7 SourceDrivenGatewayService Class Declaration


This section contains the contents of a header file (srcgates.h) which declares the class
SourceDrivenGatewayService as designed in section 4.2.7.2. Note that the class inherits all the
capabilities of the GatewayService.
#ifndef _srcgates_h
#define _srcgates_h

#include "gatesvc.h"

class SourceDrivenGatewayService

SFC Developer’s Guide 127


4.2 SFC MODELS

: public GatewayService
{
public:
// Constructor
SourceDrivenGatewayService(RTRObjectId& context,
RTRRTRecordServiceImpl& implService,
RTRRTRecordService& gateService);

// Destructor
virtual ~SourceDrivenGatewayService();

// Initialization
void load();
// Initialize the cache.

friend class GatewayRecord;


};

#endif

4.2.7.8 SourceDrivenGatewayService Class Definition


This section contains the source file which implements the class SourceDrivenGatewayService as
declared in the previous section (in srcgates.h).
The SourceDrivenGatewayService illustrates the basic technique for publishing real-time records in a
source-driven, or non-interactive, fashion. This service implements a load() method that will read a list
of symbols from the configuration database and create instances of GatewayRecord for each symbol.
This application will only publish records that are loaded at construction. By not becoming an event
client of the publishing service, this SourceDrivenGatewayService disables the ability for downstream
client components to obtain data from records that do not already reside in the publishing service.
As a descendant of GatewayService, this class inherits the ability to handle service level events from
the subscription service and to cache GatewayRecords.
At construction, the SourceDrivenGatewayService is given two other services: an
RTRRTRecordService (subscription service) from which to access data and state and a
RTRRTRecordServiceImpl (publishing service) that is used to publish the same data and state
information. The load() method is called in the constructor and is implemented to create new
GatewayRecord instances for each symbol found in a configuration value. No duplicate symbols will

SFC Developer’s Guide 128


4.2 SFC MODELS

be added. The GatewayRecord constructor takes an instance of RTRRTRecord (subscription record)


that is obtained from the subscription service. The gateway record will be publishing information from
the subscription record. Note that the GatewayRecord will add itself to the cache of this gateway
service.
After all the records have been loaded into the cache, the publishing service’s state may be initialized.
If the subscription service is in the NotStale state, then the publishing service is also initialized to the
NotState state and a ServiceSync event is sent to all downstream client components. If the
subscription service is Stale, then this class waits until the subscription service transitions to NotStale
(as indicated when the GatewayService::processServiceSync() event is called by the subscription
service).
After construction of the SourceDrivenGatewayService, no new records will be added into the
publishing service’s cache. Any requests for new records from downstream client components will be
denied automatically by the publishing service.
#include "srcgates.h" // SourceDrivenGatewayService
#include "rtr/config.h"

SourceDrivenGatewayService::SourceDrivenGatewayService(
RTRObjectId& context,
RTRRTRecordServiceImpl& implService,
RTRRTRecordService& gateService)
: GatewayService(context, implService, gateService)
{
// Initialize the cache.
load();

if (!_gateService.stale())
{
_implService.setNotStale();
_implService.setText(_gateService.text());
_implService.indicateSync();
}
};

SourceDrivenGatewayService::~SourceDrivenGatewayService(){};

void SourceDrivenGatewayService::load()
{

SFC Developer’s Guide 129


4.2 SFC MODELS

// Get a list of symbols to retrieve. If no configuration


// variable is present, use the default RTRSY.O
//
RTRListOfExternalValue ricList = RTRConfig::configDb().variable(
_classId,
_instanceId,
"symbolList",
"RTRSY.O").list(’,’);
RTRRTRecordImpl *_implRecord = 0;
for (ricList.start(); !ricList.off(); ricList.forth())
{
// Check for duplicate symbols.
if (!_implService.hasRTRecordImpl(ricList.item()))
{
// Create a new record in the _implService.
//
_implRecord = &(_implService.newRTRecordImpl( ricList.item() ));

// Get the sink record from which data will be sourced.


//
RTRRTRecord& _sinkRecord = _gateService.rtRecord( ricList.item() );

// Create a gateway record to tie together the _implRecord and


// _sinkRecord. Note that the gateway record adds and deletes
// itself from this gateway service’s cache.
//
GatewayRecord *gateRec = new GatewayRecord(_instanceId,
_sinkRecord,
*_implRecord,
*this);
if (!gateRec->active())
delete gateRec;
}
}
};

SFC Developer’s Guide 130


4.2 SFC MODELS

4.2.7.9 GatewayRecord Class Declaration


This section contains the contents of a header file (gaterec.h) which declares the class
GatewayRecord as designed in section 4.2.7.2. Note that the class inherits from both
RTRRTRecordClient (for subscription event) and RTRRTRecordImplClient (for publication events).
#ifndef _gaterec_h
#define _gaterec_h

#include "rtr/rtrecimp.h" // RTRRTRecordImpl


#include "rtr/rtrec.h" // RTRRTRecord
#include "rtr/timercmd.h"// RTRTimerCmd
#include "rtr/objid.h" // RTRObjectId
#include "rtr/logevnt.h"// RTRLogEvent

class GatewayService;

class GatewayRecord
: public RTRRTRecordImplClient,
public RTRRTRecordClient
{
public:
// Constructor
GatewayRecord(RTRObjectId& context,
RTRRTRecord& gateRec,
RTRRTRecordImpl& srcRec,
GatewayService& service);
// Destructor
virtual ~GatewayRecord();

// Identification
const RTRString& symbol() const;

// State
RTRBOOL active();

// Event processing (Inherited from RTRRTRecordClient


void processRecordInfo(RTRRTRecord& gateRec);
void processRecordSync(RTRRTRecord& gateRec);
void processRecordStale(RTRRTRecord& gateRec);
void processRecordNotStale(RTRRTRecord& gateRec);

SFC Developer’s Guide 131


4.2 SFC MODELS

void processRecordInactive(RTRRTRecord& gateRec);


void processUpdate(RTRRTRecord&);
void processTick(RTRRTRecord&);
void processCloseTick(RTRRTRecord&);
void processCorrectionTick(RTRRTRecord&);
void processUpdateComplete(RTRRTRecord& gateRec);
void processRecordResync(RTRRTRecord& gateRec);
void processResyncComplete(RTRRTRecord& rec);

// From RTRRTRecordImplClient
void processHasEventClient(RTRRTRecordImpl&);
// Handle the case where the first downstream client has
// started watching the record

void processNotHasEventClient(RTRRTRecordImpl&);
// Handle the case where the last downstream client has
// stopped watching the record.

protected:
RTRRTFieldUpdateList _updList;
RTRRTRecordImpl& _implRecord;
RTRRTRecord& _gateRecord;
GatewayService& _service;
static RTRLogEvent _logEvent;
RTRObjectId _instanceId;
};

#endif

4.2.7.10 GatewayRecord Class Definition


This section contains the source file which implements the class GatewayRecord as declared in the
previous section (in gaterec.h).
This class primarily acts as a "glue" layer between a RTRRTRecord instance (subscription record) and
a RTRRTRecordImpl instance (published record).
At construction, the gateway record registers with both the subscription record and published record to
receive events. Then the gateway record checks to make sure the subscription record is valid
(_gateRecord.active()) and adds itself to the gateway service. If the subscription record is fully

SFC Developer’s Guide 132


4.2 SFC MODELS

populated (_gateRecord.hasData()), then the published record is populated with fields and its state is
initialized by calling the processRecordSync() method. If the subscription record is not populated yet,
then the gateway record will wait until the subscription record sends a Sync event.
The processRecordSync() method is implemented to iterate through all the fields found in the
subscription record and add a new field of the same type into the published record. To do this, an
instance of RTRRTRecordIterator is obtained from the subscription record and, for each field in the
iteration, a new field of the same type is created. It is possible that the publishing service’s FID
database will not contain all the same fields as the subscription service. When this occurs, the gateway
record will ignore the field.
Note that the RTRFidDefinitions passed to the constructor of each new field are obtained from the
RTRFidDb of the publishing service. Since the subscription and publishing services can have different
FID databases, the gateway application must get the FID definitions from the publishing service.

NOTE: Use the field name (RTRRTField.name()) when querying the FID database for a FID defini-
tion. The field names are more likely to be consistent across different system’s FID databases. This
is true of the RMDS and SSL systems, where the field ID values tend to be inconsistent, while the
field names are consistent.

After the new fields are populated into the published record, the record’s state is changed to reflect that
of the subscription record and a RecordSync event is propagated to all downstream client
components.
As updates occur in the subscription record, the processUpdateComplete() method is called. This
method is implemented to iterate through all the fields that have updated in the subscription record and
reset the values of the corresponding published record. After all fields have been updated, the list of
fields is passed to the published record and an UpdateComplete event is propagated to all
downstream client components.
The same processing occurs when the subscription record is resynchronized, or refreshed, and the
processResyncComplete() method is called.
As other events are received from the subscription record, the events are reflected in the published
record. Whenever a subscription record state change event occurs, the published record’s state and
descriptive text are changed and the same event is propagated to the published record.
If a RecordInactive event is received from the subscription record, the gateway record will propagate
the event to the published record, remove the published record from the publishing service, remove

SFC Developer’s Guide 133


4.2 SFC MODELS

itself from the gateway service, de-register from the subscription and published records and then
destroy itself. An Inactive event is a permanent indication that the symbol is no longer valid.
Note that the processHasEventClient() and processNotHasEventClient() callbacks are not
implementated to take any action. This is because, for the purposes of this example program, the
record will remain cached for the life of the application once it is added
#include "gaterec.h"
#include "gatesvc.h"

GatewayRecord::GatewayRecord(RTRObjectId& context,
RTRRTRecord& gateRec,
RTRRTRecordImpl& srcRec,
GatewayService& service)
: _gateRecord(gateRec), _implRecord(srcRec),
_instanceId(context, gateRec.symbol()),
_service(service), _updList(srcRec)
{
RTPRECONDITION( !service.hasRecord(gateRec.symbol()) );

_implRecord.setStale();
_implRecord.addClient(*this);
_gateRecord.addClient(*this);
if ( _gateRecord.active() )
{
_service.addRecord(this);
if ( _gateRecord.hasData() )
{
processRecordSync(_gateRecord);
}
else
{
_implRecord.setText(_gateRecord.text());
_implRecord.indicateInfo();
}
}
else
{
_gateRecord.dropClient(*this);
}
};

SFC Developer’s Guide 134


4.2 SFC MODELS

GatewayRecord::~GatewayRecord()
{
_implRecord.dropClient(*this);
_implRecord.setText(_gateRecord.text());

if (_gateRecord.hasClient(*this))
_gateRecord.dropClient(*this);

// Notify any clients of state change.


_implRecord.setInactive();
_implRecord.indicateInactive();

// Delete all fields and allocated field memory.


_implRecord.deleteAllFields();

// Remove the impl record from it’s RTRRTRecordServiceImpl.


_implRecord.service().removeRTRecordImpl(_implRecord.symbol());

// Remove this gateway record from the GatewayService.


_service.removeRecord(symbol());
};

const RTRString& GatewayRecord::symbol() const


{
return _gateRecord.symbol();
}

RTRBOOL GatewayRecord::active()
{
return _gateRecord.active();
};

void GatewayRecord::processRecordInfo(RTRRTRecord& gateRec)


{
_implRecord.setText(gateRec.text());
_implRecord.indicateInfo();
};

void GatewayRecord::processRecordSync(RTRRTRecord& gateRec)

SFC Developer’s Guide 135


4.2 SFC MODELS

{
RTRRTRecordIterator iter = gateRec.iterator();

char* farea;
RTRRTField *fld = 0;

// If template number exists in upstream record,


// on-pass it to published record.
//
if (gateRec.recordTemplateNumber() != 0)
_implRecord.setRecordTemplateNumber(gateRec.recordTemplateNumber());

// Create new fields for each of the fields found in


// the gateRec.
//
for (iter.start(); !iter.off(); iter.forth())
{
RTRRTField& field = iter.field();
const RTRFidDefinition *def = _implRecord.fidDb().defByName(field.name());

if (def)
{
// NOTE: Always allocate one extra byte for storing the
// end-of-data delimiter.
int fLength = def->length() + 1;

if (field.type() == RTRFidDefinition::Price)
{
farea = new char [fLength];
fld = new RTRRTPriceField(*def, farea, 0);
}
else if (field.type() == RTRFidDefinition::Alphanumeric ||
field.type() == RTRFidDefinition::LongAlphanumeric )
{
farea = new char [fLength];
fld = new RTRRTAlphanumericField(*def, farea, 0);
}
else if (field.type() == RTRFidDefinition::TimeSecs ||
field.type() == RTRFidDefinition::Date ||
field.type() == RTRFidDefinition::Time )

SFC Developer’s Guide 136


4.2 SFC MODELS

{
farea = new char [fLength];
fld = new RTRRTDateTimeField(*def, farea, 0);
}
else if (field.type() == RTRFidDefinition::Integer)
{
farea = new char [fLength];
fld = new RTRRTIntegerField(*def, farea, 0);
}
else if (field.type() == RTRFidDefinition::Numeric)
{
farea = new char [fLength];
fld = new RTRRTNumericField(*def, farea, 0);
}
else if (field.type() == RTRFidDefinition::Enumerated)
{
int eLength = def->expandedLength() + 1;
if(eLength > fLength)
farea = new char [eLength];
else
farea = new char [fLength];
const RTREnumTable *tbl =
_implRecord.fidDb().enumTableByName(field.name());
fld = new RTRRTEnumeratedField(*def, farea, 0, *tbl);
}
else
{
farea = new char [fLength];
fld = new RTRRTField(*def, farea, 0);
}
// Set the field value.
fld->set(field.to_c(), field.count());

// Add the field to the publication record.


_implRecord.putField(*fld);
}
}

if (!gateRec.stale())
_implRecord.setNotStale();

SFC Developer’s Guide 137


4.2 SFC MODELS

_implRecord.setText(gateRec.text());
_implRecord.indicateSync();
};

void GatewayRecord::processRecordStale(RTRRTRecord& gateRec)


{
_implRecord.setStale();
_implRecord.setText(gateRec.text());
_implRecord.indicateStale();
};

void GatewayRecord::processRecordNotStale(RTRRTRecord& gateRec)


{
_implRecord.setText(gateRec.text());
_implRecord.setNotStale();
_implRecord.indicateNotStale();
};

void GatewayRecord::processRecordInactive(RTRRTRecord&)
{
// Note - clean up of gate and impl records is done in
// the destructor.
delete this;
};

void GatewayRecord::processUpdate(RTRRTRecord&)
{
_implRecord.indicateUpdateTick();
};

void GatewayRecord::processTick(RTRRTRecord&)
{
_implRecord.indicateUpdateTick();
};

void GatewayRecord::processCloseTick(RTRRTRecord&)
{
_implRecord.indicateCloseTick();
};

SFC Developer’s Guide 138


4.2 SFC MODELS

void GatewayRecord::processCorrectionTick(RTRRTRecord&)
{
_implRecord.indicateCorrectionTick();
};

void GatewayRecord::processUpdateComplete(RTRRTRecord& gateRec)


{
RTRRTRecordUpdateIterator iter = gateRec.updateIterator();

_updList.reinitialize(_implRecord);
for (iter.start(); !iter.off(); iter.forth())
{
// Update the _implRecord’s field with the value
// from the _gateRecord’s field.
//
RTRRTField& gateFld = iter.field();
RTRRTField& implFld = *_implRecord.fieldByName(gateFld.name());
if (&implFld)
{
implFld.set(gateFld.to_c(), gateFld.count());
_updList.putField(implFld);
implFld.indicateFieldUpdated();
}
}

_implRecord.indicateUpdateComplete(_updList);
};

void GatewayRecord::processRecordResync(RTRRTRecord& gateRec)


{
_implRecord.setText(gateRec.text());
if (gateRec.stale())
_implRecord.setStale();
else
_implRecord.setNotStale();
_implRecord.indicateResync();
};

void GatewayRecord::processResyncComplete(RTRRTRecord& gateRec)


{

SFC Developer’s Guide 139


4.2 SFC MODELS

RTRRTRecordUpdateIterator iter = gateRec.updateIterator();

_updList.reinitialize(_implRecord);
for (iter.start(); !iter.off(); iter.forth())
{
// Update the _implRecord’s field with the value
// from the _gateRecord’s field.
//
RTRRTField& gateFld = iter.field();
RTRRTField& implFld = *_implRecord.fieldByName(gateFld.name());
if (&implFld)
{
implFld.set(gateFld.to_c(), gateFld.count());
_updList.putField(implFld);
implFld.indicateFieldUpdated();
}
}

_implRecord.indicateResyncComplete(_updList);
};

// From RTRRTRecordImplClient
void GatewayRecord::processHasEventClient(RTRRTRecordImpl&)
{
_logEvent.setComponent(_instanceId);
_logEvent.setText("Users are now monitoring this record.");
_logEvent.setSeverity(RTRLogSeverity::debug);
_logEvent.log();
};

void GatewayRecord::processNotHasEventClient(RTRRTRecordImpl&)
{
_logEvent.setComponent(_instanceId);
_logEvent.setText("Users are no longer monitoring this record.");
_logEvent.setSeverity(RTRLogSeverity::debug);
_logEvent.log();
};

RTRLogEvent GatewayRecord::_logEvent;

SFC Developer’s Guide 140


4.3 SFC MODELS

4.3 Page Subscription

4.3.1 Overview

4.3.1.1 Pages
A page represents an item of market data which is paginated, i.e., the data has embedded formatting
and display information. This is done by encoding escape sequences in the data or by providing
formatting data in a separate attribute field. It is this embedded display information that differentiates
pages from records. In Triarch and RMDS, pages are sometimes called ANSI pages. In TIB, they are
referred to as effects pages.
In all other ways, pages represent real-time market data, just like records. The content of a page may
change over time. These changes are referred to as updates and constitute distinct events which must
be conveyed to the clients of any given page. Page clients are application components which are
interested in the events associated with a particular page. This interest is expressed by the act of
registering a client with a page.
The data represented by a page can be characterized by its condition. The condition of the data may
affect the way in which it is used by a client. For example, if data is suspect, or stale, a display
application might indicate this by using a different color to display that data. Data condition is
expressed in the model by state variables associated with a page. Changes in the condition of the data
result in changes to page state. As with updates, page state changes are generally of interest to
clients, requiring timely propagation of these events to individual clients of the page.
Some services support a "next" and "previous" page. The names of these adjacent pages are
dependent on the service and the infrastructure. The infrastructure-specific names are available from
the page.

4.3.1.2 Logical Pages


SFC has two models for representing pages: logical pages and page streams. The second model,
page "streams," is only available for the Triarch infrastructure and is discussed in section 4.4. While
the RMDS infrastructure does provide page data in an ANSI format, the legacy page stream model is
not supported for the RMDS infrastructure. The logical model is preferred.
Logical pages separate the data from the attributes and split the data into regions. A page region is a
single row of cached data, with a starting and an ending column. Each column of a region is called a
cell. The data and attributes of logical page are always cached.

SFC Developer’s Guide 141


4.3 SFC MODELS

The logical page abstraction is represented in SFC by the class RTRPage. Page regions are
represented by the class RTRPageRegion. Clients can register interest in a page’s state and data
events with the interface RTRPageClient. They can register interest in an individual region using the
interface RTRPageRegionClient.

4.3.1.3 Attributes
Logical pages also include attributes that describe how the data should be displayed. They can
describe properties such as highlighting, inverse printing, and colors. Attributes are stored with the
page, so an individual cell’s attribute data can be accessed from the page. A page actually stores two
sets of attributes, the normal attributes and the fade attributes. The fade attributes are used to
temporarily highlight regions that have updated. Figure 4.13 shows the object structure of a RTRPage
.

RTRPageAttributes
2..1

RTRPageRegion
RTRPage 1..n

1..n
RTRPageClient 1..n

RTRPageRegionClient
+processSync()
+processUpdate()
+processUpdate()
+processRename()
+processInactive()
+processInfo()
+processResync()
+processStale()
+processNotStale()

Figure 4.13: Logical Page Class Model

SFC Developer’s Guide 142


4.3 SFC MODELS

A page’s attributes describe how each cell within the page should be displayed. All of a page’s
attributes are stored in a single object of type RTRPageAttributes. The page model supports the
following attributes:
• background color - enumeration of type RTRPageAttributes::Color
• foreground color - enumeration of type RTRPageAttributes::Color
• character set - enumeration of type RTRPageAttributes::CharSet
Character sets can be used to select a display character set that supports the necessary
extended ASCII characters (character above127).
• blink - RTRBOOL
• bold (also called bright) - RTRBOOL
• dim - RTRBOOL
• overline - RTRBOOL
• reverse - RTRBOOL
• underline - RTRBOOL

4.3.1.4 Services and Service Pools


Page services and page service pools are analogous to real-time record services and record service
pools. The only difference is that they provide access to pages instead of records. Please refer to
section 4.1.1.5 and section 4.1.1.6 for a discussion of the roles of services and pools in an application.
The relavent logical page classes are RTRPageService, RTRPageServicePool, and
RTRPageServicePoolClient.

4.3.2 Design

4.3.2.1 Page State


Logical page state is defined by the values of three page attributes:
• stale
• active
• hasData

SFC Developer’s Guide 143


4.3 SFC MODELS

State transitions are propagated to clients as events on the RTRPageClient interface. Figure 4.14
shows page states and events causing state transitions. The state transition diagram is the same as
the one for records.

Sync
Active_noData Active_valid
Inactive Resync
Inactive Sync
Stale
NotStale

Inactive Inactive Active_stale


Resync

Active_noData (hasData = False, stale = True, active = True)


Active_valid (hasData = True, stale = False, active = True)
Active_stale (hasData = True, stale = True, active = True)
Inactive (hasData = XX, stale = XX, active = False)

Figure 4.14: Logical Page States and Variables

4.3.2.2 Service State


Page service state is identical to record service state. It even uses the same RTRMDConnectionClient
interface. For more details see section 4.1.2.4.

4.3.3 Class Summary


This section provides a summary of the classes which comprise the model for real-time page data. For
more details please refer to the appropriate sections of the alphabetical class reference.

SFC Developer’s Guide 144


4.3 SFC MODELS

• RTRPage - This class defines an item of real-time page data that has been shredded into a
logical format. A RTRPage maintains an ordered list of RTRPageRegions and the attribute
information for the page. Also, it keeps track of the state of the market data item.
• RTRPageClient - This is the abstract base class for application components that wish to register
with one or more real-time pages in order to receive data and state events from those pages.
• RTRPageRegion - This class stores the data for a single row of a page.
• RTRPageRegionClient - This is the abstract base class for application components which wish
to register to receive data events for one or more page regions.
• RTRPageRegionIterator - This class provides sequential access to all regions in a page.
• RTRPageRegionUpdate - This class is used during page updates to keep track of the offsets in a
page region that were updated. It is only valid during a RTRPageClient::processUpdate() or a
RTRPageRegionClient::processUpdate() callback.
• RTRPageRegionUpdateIterator - During a RTRPageClient::processUpdate() callback, this
class provides sequential access to the regions that were updated.
• RTRPageAttributes - This class stores all of the attributes of a page. Attributes for a single page
cell can be accessed by specifying the row and column.
• RTRPageService - This class provides access to real-time page data and manages the
aggregate state of those pages. Service state change events are propagated to those application
components that register to receive those events.
• RTRMDServiceClient - This is the abstract base class for components that wish to register with
one or more instances of page or record services in order to receive data and state events from
those services.
• RTRPageServicePool - Instances of this class serve as a repository for all available real-time
page services. Typically there is only one instance of this type within an application. A pool
provides random and sequential access to the services it contains. A pool provides the means to
insert and remove services and allows clients to register for the change events which are
generated when the contents are modified.
• RTRPageServicePoolClient - This is the abstract base class for components that wish to
register with one or more real-time page service pools in order to receive data and state events
from those pools. This interface does not indicate when the state of a service changes. To monitor

SFC Developer’s Guide 145


4.3 SFC MODELS

state changes in a service (e.g. when a service becomes stale), register directly with the service
using RTRMDServiceClient.

4.3.4 Implementation
Currently, the SFC provides two implementations of the real-time page model, although other
implementations are possible. While most application components should refer only to the base
classes mentioned in the preceding section, the "main" routine or initialization section of an application
must instantiate one or more implementation specific classes. The implementation classes mentioned
here are similar in functionality and implementation to those that provide access to real-time record
data and which are presented in section 4.1.3. Please refer to that section for more details.
The SFC page model includes implementation classes for use by both single (simple) and multiple
service (more complex) applications. These classes encapsulate the procedures for creating an SSL
connection and the page services which use that connection. They are:
• RTRSSLPageService - This class is a descendant of RTRPageService and creates is own
RTRRTPageService to retrieve data. It is typically used by simple applications which require
access to only a single service.
• RTRTIBPageService - This class is a descendant of RTRPageService which creates its own TIB
connection. It is typically used by simple applications which require access to only a single
service.

4.3.4.1 Character Sets


The TIB infrastructure does not provide character set information with its data. So, when getting data
from a TIB infrastructure, the TIB implementation is dependent on a character mapping file,
charMapFile.cnf. By default, the TIB Implementation looks for this file in /var/triarch. See the
comments in the file for information on the file format. Several services have already been configured
in this file. This file’s format may change in the future. See section 5.5.8.2 for further information.

4.3.4.2 Attribute Mapping


Most attribute information is boolean, meaning the attribute is either on or off. For memory and
bandwidth considerations, attribute data is encoded into one or two bytes. For example, the first bit
may represent bold while the third bit represents underline. Each system that supports attributes does
so in a different encoding format. TIB, Triarch, the curses display library, and the WinConsole API all
encode this data differently. SFC decodes attribute information from TIB and Triarch page services so

SFC Developer’s Guide 146


4.3 SFC MODELS

the Triarch and TIB formats do not have to be interpreted by the application. Typical applications will
still need to map attributes from SFC boolean function values to the display API’s encoding format.
The WinPage and CursesPage examples have functions that map SFC semantic attributes to display
attributes.
TIB services do not deliver fade attributes, so SFC will return the same data for
RTRPage::attributes() and RTRPage::fadeAttributes().
Some datafeeds for TIB page services do not use the TIB standard method for encoding attributes.
Instead of sending color information, they encode the colors in the attribute fields. SFC provides a
mechanism for mapping these attributes to the correct TIB-semantic attributes. For more information
on configuring a TIB page service, see section 5.5.8.2.

4.3.4.3 Configuration
Both implementations provide the following configuration variables for setting up a page service:
• enableColors - should colors be enabled (default is true)
• defaultFgColor - set the default foreground color (7 for white)
• defaultBgColor - set the default background color (0 for black)

4.3.4.4 Multiple Services


Some applications use more than one service. The connection and service pool factory classes make
it easy to incorporate multiple services in a single application.
RTRSSLConnection and RTRTIBConnection can be used to fine tune the connection parameters for
the implementation page services. They are described in detail in section 4.8.1.
RTRSSLServicePoolFactory and RTRTIBServicePoolFactory can be used to manage the life-cycle of
and share a single connection among several market data services. They are described in detail in
section 4.8.2.

4.3.5 Examples
SFC includes a few examples that highlight different parts of the page model. These examples can be
found the sfc/examples/pages/ directory. They typically have two parts:
1. main() function that:

SFC Developer’s Guide 147


4.3 SFC MODELS

• parses command line arguments


• creates a service pool factory or page service
• requests a page
• creates the appropriate SFC client and registers it with the page
• creates the event control loop
2. SFC client implementation that is responsible for:
• processing data and status events
• printing output to standard out
The following table summarizes the record examples and details where more information about them
can be found.

Example
Description Refer to...
Program

PageUpd Displays a page’s image, updates and events to stan- pageupdclient.*


dard out. pageupd.C
section 4.3.6

RegionUpd Displays updates from a single region from a page. regionupdclient.*


regionupd
section 4.3.7

WinPage Displays a page’s data and applies its attributes to a section 4.3.8
(win32 only) Windows console using Win32 platform SDK functions. winpage.C
consolepageclient.*
(win32 only)

CursesPage Displays a page’s data and applies its attributes to an section 4.3.8
(Unix only) xterm using the X-Open curses library. cursespage*.*
(Unix only)

Table 4.11: Page Examples

4.3.6 Page Client


The PageUpd example prints a page’s status and data events on the standard output device.
Attributes are ignored. The entire page is printed when a Sync, Resync or Update event is received.

SFC Developer’s Guide 148


4.3 SFC MODELS

The name of this class is PageUpdClient. In order to receive page events, this class is a descendant of
RTRPageClient. This class must provide implementations of all pure virtual methods inherited from its
ancestor. These methods correspond to the events that can be received from RTRPage.
This class processes these events:
• Sync
• Resync
• Stale
• NotStale
• Info
• Inactive
• Rename
• Update

4.3.6.1 Declaration of PageUpdClient (pageupdclient.h)


// PageUpdClient is a concrete implementation of RTRPageClient.
// It prints the entire page when an image is initially received
// and when any part of the page updates.

#ifndef _pageupdclient_h_
#define _pageupdclient_h_

#include "rtr/page.h"
#include "rtr/pgreg.h"

class RTRPageService;

class PageUpdClient :
public RTRPageClient
{
public:
PageUpdClient(RTRPageService &service, RTRString &ric);
virtual ~PageUpdClient();

SFC Developer’s Guide 149


4.3 SFC MODELS

// RTRPageClient
virtual void processSync(RTRPage&);
virtual void processResync(RTRPage&);
virtual void processStale(RTRPage&);
virtual void processNotStale(RTRPage&);
virtual void processInfo(RTRPage&);
virtual void processInactive(RTRPage&);
virtual void processUpdate(RTRPage&);
virtual void processRename(RTRPage&);

protected:
RTRPage *_page;
};

#endif

4.3.6.2 Definition of PageUpdClient (pageupdclient.C)


#include "pageupdclient.h"
#include "rtr/pgsrvc.h"

PageUpdClient::PageUpdClient(RTRPageService &service, RTRString &ric)


{
_page = &(service.page(ric));
_page->addClient(*this);
}

PageUpdClient::~PageUpdClient()
{
if (_page && _page->hasClient(*this))
_page->dropClient(*this);
}

void PageUpdClient::processSync(RTRPage &page)


{
cout << page.symbol() << ": page sync" << endl;

// print the entire page


cout << *_page;
}

SFC Developer’s Guide 150


4.3 SFC MODELS

void PageUpdClient::processResync(RTRPage &page)


{
cout << page.symbol() << ": page resync" << endl;
cout << *_page;
}

void PageUpdClient::processStale(RTRPage &page)


{
cout << page.symbol() << ": page stale: " << page.text() << endl;
}

void PageUpdClient::processNotStale(RTRPage &page)


{
cout << page.symbol() << ": page not stale" << endl;
}

void PageUpdClient::processInfo(RTRPage &page)


{
cout << page.symbol() << ": page info: " << page.text() << endl;
}

void PageUpdClient::processInactive(RTRPage &page)


{
cout << page.symbol() << ": page inactive" << endl;
_page->dropClient(*this);
_page = 0;
}

void PageUpdClient::processRename(RTRPage &page)


{
// This event occurs when a next or previous page is requested. The new
// page name is automatically requested by SFC unless page.dropClient()
// is called here.
cout << page.symbol() << ": page renamed" << endl;
}

void PageUpdClient::processUpdate(RTRPage &page)


{

SFC Developer’s Guide 151


4.3 SFC MODELS

cout << page.symbol() << ": page sync" << endl;


cout << *_page;
}

4.3.6.3 Creating Page Service and PageUpdClient


The following code shows how to create an SSL or TIB page service. It is similar in structure to the
RecSnap example in section 4.1.6.3.

// Some of the code has been omitted for brevity.


// See sfc/examples/realtime/recsnap.C for all of the code

#include "pageupdclient.h"
#include "rtr/selectni.h"// RTRSelectNotifier
#include "rtr/tibpgsrvc.h"
#include "rtr/sslpgsrvc.h"

RTRCmdLine RTRCmdLine::cmdLine;

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


{
RTRString serviceName, infra, symbol;
RTRString servicePort, network, daemon;

// Read command line parameters, set serviceName, infra, and symbol.


// For TIB, also set servicePort, network, and daemon.
// ...

RTRPageService *service = 0;

// Select which architecture to consume from


if (infra == "tib")
{
service = new RTRTIBPageService(appId, serviceName,
servicePort, network, daemon);
}
else if (infra == "ssl")
{

SFC Developer’s Guide 152


4.3 SFC MODELS

service = new RTRSSLPageService(appId, serviceName);


}
else
{
cout << "invalid infrastructure: " << infra << endl;
return -1;
}

if ( !service->active() )
{
cerr << "Service error: " << service->text() << endl;
delete (service);
return -1;
}

PageUpdClient client(*service, symbol);


RTRSelectNotifier::run();
delete service;
return 0;
}

4.3.7 Region Client


RegionUpdClient is similar to PageUpdClient, except it ignores page updates and focuses on updates
for a single region. The specific differences in the declaration include:
• includes "rtr/pgreg.h"
• inherits from RTRPageRegionClient
• declares void processUpdate(RTRPageRegionUpdate&);
• constructor accesses a short, which is the row number (1-based) of the region to monitor
• stores the row number and region pointer in variables

4.3.7.1 Definition of RegionUpdClient (regionupdclient.C)


The definition is also very similar to pageupdclient.C. Some the file’s code has been omitted for
brevity. The key differences are shown below in processSync(RTRPage &),
processUpdate(RTRPageRegion&), and the destructor.

SFC Developer’s Guide 153


4.3 SFC MODELS

#include "regionupdclient.h"

// ...

RegionUpdClient::~RegionUpdClient()
{
if (_region && _region->hasClient(*this))
_region->dropClient(*this);
if (_page && _page->hasClient(*this))
_page->dropClient(*this);
}

void RegionUpdClient::processSync(RTRPage &page)


{
cout << page.symbol() << ": page sync" << endl;
_region = page.getRegion(_row);
if (_region)
_region->addClient(*this);
cout << _page->symbol() << " - " << _row << endl;
cout << _region->value() << endl;
}

// ...

void RegionUpdClient::processUpdate(RTRPageRegionUpdate &update)


{
cout << "Page: " << _page->symbol() << " - row: " << _row << ": ("
<< update.start() << "," << update.stop() << ")" << endl;
cout << update.region().value() << endl;
}

4.3.8 Attribute Examples


SFC includes two examples that take attribute data from logical pages and apply it to a display
environment. The winpages example for Win32 platforms uses the Windows console system
functions. The cursespage example for Unix platforms uses the X-Open curses library for xterms. Both
applications follow a similar process:

SFC Developer’s Guide 154


4.3 SFC MODELS

1. Request the page supplied at the command line.


2. Whenever a data event is received, extract the RTRPageAttributes from the page.
3. For each row and column changed in the update, check each of the attributes that are
supported by the display environment (for example, colors are supported by a Windows
console, but not by all xterms). If the attribute is true, enable that attribute for the target
attribute encoding. This process maps the SFC encoding of attributes to the display
environments encoding of attributes.
4. When attribute mapping has been completed, display the data and mapped attribute
information using the appropriate system library calls.
Each example may also go through some display environment-specific process which is independent
of SFC.

SFC Developer’s Guide 155


4.4 SFC MODELS

4.4 Page Stream Subscription


NOTE: The Page Stream model is a legacy model, only available for Triarch. It is included with
SFC for backwards compatibility. All new development should use the logical page model.

4.4.1 Overview

4.4.1.1 Page Streams


The second model for page data is stream-based. A page stream makes no attempt to decode the
data. It just delivers it to its clients. The page stream abstraction is represented in SFC by the class
RTRRTPage. Note that the class names for page streams include the RT prefix between the RTR-
prefix and the base class name. The new logical page classes dropped the extra RT. This does not
imply one model is more "real-time" than the other. The naming distinction simply maintains backwards
compatibility for the legacy stream classes while avoiding name conflicts with the logical page model.
Stream pages are a particular type of real-time data stream. Streams provide encoded data
representing images and updates. What makes a page a page is the type of encoding used. A stream
(page) is not required to cache the most recent image, although it may choose to do so. Clients of a
stream may request an image for that stream and will then receive an image and subsequent updates
to that image. Because stream clients have state with respect to a particular stream (some clients may
have received an image and consider the stream "not current" or stale, while others may not have
received an image and hence consider the stream stale), clients may only register with one stream at a
time, although a given stream can support multiple clients. The page client abstraction is represented
in the SFC by the class RTRRTPageClient.

4.4.1.2 Services
Real-time page services are very similar to real-time record services, except that they provide pages
instead of records. As with record services, if a page service is unable (or unwilling) to provide data for
a requested page, the page will be in an inactive state. The text of an inactive page explains the
reason that data will not be provided. Once in an inactive state, a page will never transition to the
active state. Applications should not maintain references (pointers) to inactive items. This rule is based
on practical considerations, e.g. memory management. Resources used by inactive items are eligible
to be reclaimed. In the SFC, logical page services are represented by the class RTRPageService, and
page stream services are represented by the class RTRRTPageService.

SFC Developer’s Guide 156


4.4 SFC MODELS

4.4.1.3 Service Pools


Real-time page services and page service pools are similar to real-time record services and record
service pools. Please refer to sections 4.1.1.5 and 4.1.1.6 for a discussion of the role of services and
pools in an application. The relevant logical page classes are RTRPageService,
RTRPageServicePool, and RTRPageServicePoolClient. The equivalent stream page classes are
RTRRTPageService, RTRRTPageServicePool, and RTRRTPageServicePoolClient.

4.4.2 Design

4.4.2.1 Page State


Since page stream data is not cached, hasData for a stream page is never true. Page stream state is
defined by the values of only two page attributes:
• stale
• active.
State transitions are propagated to clients as events on the RTRRTPageClient interface. Figure 4.15
shows page states and events causing state transitions.

Stale
Active_valid Active_stale
NotStale

Inactive
Inactive

Inactive

Active_valid (stale = False, active = True)


Active_stale (stale = True, active = True)
Inactive (stale = XX, active = False)
Figure 4.15: Real-time Page Stream States and Variables

SFC Developer’s Guide 157


4.4 SFC MODELS

4.4.2.2 Service State


Page service state is identical to record service state. It even uses the same RTRMDConnectionClient
interface. For more details see section 4.1.2.4.

4.4.3 Class Summary


This section provides a summary of the classes which comprise the model for real-time page data. For
more details please refer to the appropriate sections of the alphabetical class reference.
• RTRRTPage - This class defines an item of real-time page data. Pages represent a stream which
provides an image/update model of access to encoded data. Pages support multiple clients which
are application components that register with an individual page for data and state events from
that page. Because pages are not required to cache an image of the current data, the state of a
stream depends in part on the state of the client "viewing" the stream. A page provides the means
for clients to request a refresh of the current image, which is presented as an encoded sequence
including both character data and presentation attributes encoded for display on character
terminals.
• RTRRTPageClient - This is the abstract base class for application components which wish to
register with one or more real-time pages in order to receive data and state events from those
pages.
• RTRRTPageService - This class provides access to real-time page data and manages the
aggregate state of those pages. Service state change events are propagated to those application
components which register to receive those events.
• RTRMDServiceClient - This is the abstract base class for components which wish to register
with one or more instances of page or record services in order to receive data and state events
from those services.
• RTRRTPageServicePool - Instances of this class serve as a repository for all available real-time
page services. Typically there is only one instance of this type within an application. A pool
provides random and sequential access to the services it contains. A pool provides the means to
insert and remove services and allows clients to register for the change events which are
generated when the contents are modified.
• RTRRTPageServicePoolClient - This is the abstract base class for components which wish to
register with one or more real-time page service pools in order to receive data and state events
from those pools. This interfaces does not indicate when the state of a service changes. To

SFC Developer’s Guide 158


4.4 SFC MODELS

monitor state changes in a service (e.g. when a service becomes stale), register directly with the
service using RTRMDServiceClient.
• RTRBufferReadIterator - This class provides access to the encoded page images and updates.

4.4.4 Implementation
Currently, the SFC provides an SSL based implementation of the real-time page model, although other
implementations are possible. While most application components should refer only to the base
classes mentioned in the preceding section, the "main" routine or initialization section of an application
must instantiate one or more implementation specific classes. The implementation classes mentioned
here are similar in functionality and implementation to those which provide access to real-time record
data and which are presented in section 4.1.3. Please refer to that section for more details.
The SFC page model includes implementation classes for use by both single (simple) and multiple
service (more complex) applications. These classes encapsulate the procedures for creating an SSL
connection and the page services which use that connection. They are:
• RTRDefaultRTPageService - This class is a descendant of RTRRTPageService (via
RTRSSLRTPageService) which creates its own SSL session. It is typically used by simple
applications which require access to only a single service.
• RTRDefaultRTPageServicePool - This class is a descendant of RTRRTPageServicePool which
creates its own SSL session and monitors that session for page based services. For each
observed service, the pool adds to itself an instance of RTRSSLRTPageService. Other
application components can, as usual, monitor the pool for new services without being dependent
on SSL implementation details.

4.4.5 Examples
Please refer to the alphabetical reference section and the relevant example programs for more details
concerning these classes. Examples are presented for:

Type of
Name Description Refer to...
Example

Class AnsiPageSnapshotClient Simple page client component to section 4.4.6


get snapshot of page

Table 4.12: Page Stream Examples

SFC Developer’s Guide 159


4.4 SFC MODELS

Type of
Name Description Refer to...
Example

Application ansipagesnap.C Creates single instance of section 4.4.7


AnsiPageSnapshotClient

Class AnsiPageUpdateClient Monitors updates from page section 4.4.8

Application ansipageupd.C Creates single instance of end of section


AnsiPageUpdateClient 4.4.8

Table 4.12: Page Stream Examples (Continued)

4.4.6 Example Class — Simple Page Client


The purpose of this class is to print a snapshot of a page image on the standard output device. Bear in
mind that page data contains embedded escape sequences for presentation on VT100 style terminals.
This page client is not concerned with updates or any other events once the initial image as been
extracted. The name of this class is AnsiPageSnapshotClient. In order to receive page events, this
class is a descendant of RTRRTPageClient. This class must provide implementations of all pure virtual
methods inherited from its ancestor. These methods correspond to the events that can be received
from RTRRTPage. In this case, some of the event processing methods are implemented to do nothing
because this class is not interested in the events in question.
This class processes the following events:
• StreamInfo
• StreamSync
• StreamInactive
This class ignores these events:
• StreamResync
• StreamStale
• StreamUpdate
• StreamRename - note that unlike the logical page model, renamed streams are not automatically
re-requested by SFC

SFC Developer’s Guide 160


4.4 SFC MODELS

4.4.6.1 Declaration of AnsiPageSnapshotClient (ansipagesnapclient.h)


//
// This file contains the declaration of AnsiPageSnapshotClient which
// illustrates the basic techniques for processing page events. This
// class is designed to take a snap-shot of the data for a single page.
//

#ifndef _ansipagesnapclient_h
#define _ansipagesnapclient_h

#include "rtr/rtpage.h"// Defines RTRRTPageClient

class AnsiPageSnapshotClient :
public virtual RTRRTPageClient
{
public:
// Constructor
AnsiPageSnapshotClient(RTRRTPageService&, const char *);

// Destructor
~AnsiPageSnapshotClient();

// Attributes - from RTRRTPageClient


RTRRTPage *page();

// Event processing
void processStreamResync(RTRBufferReadIterator& ) {};
// The stream has new image. It may still be stale. Clients should
// check the condition of the stream. It is not relevant here, since
// this class takes a snap-shot and teriminates the application.

void processStreamSync(RTRBufferReadIterator& iter);


// The stream has an image. It may still be stale. Clients should check
// the condition of the stream.

void processStreamStale() {};


// The stream data is out-of-date. Stream state information is
// available via text(). It is not relevant here, since this
// class takes a snap-shot and teriminates the application.

SFC Developer’s Guide 161


4.4 SFC MODELS

void processStreamNotStale() {};


// The stream is no longer stale. It is not relevant here, since this
// class takes a snap-shot and teriminates the application.

void processStreamInactive();
// The stream is invalid. Drop all references immediately. Resources
// consumed by the stream will be reclaimed by the service which
// provided it.

void processStreamInfo();
// The stream has new informational text. The state of the
// stream has not changed.

void processStreamUpdate(RTRBufferReadIterator& ) {};


// The stream has updated update event processing.
// It is not relevant here, since this class
// takes a snap-shot and teriminates the application.

protected:
// Implementation attributes
RTRRTPage *_page;
};

#endif

4.4.6.2 Definition of AnsiPageSnapshotClient (ansipagesnapclient.C)


This constructor of this class illustrates the correct procedure to use in accessing pages from a
service. In pseudo-code the procedure is as follows:
Get page reference
add client to page
If page active then
If page has image then
process image and data condition
else
clean up

SFC Developer’s Guide 162


4.4 SFC MODELS

Page data is made available through an instance of RTRBufferReadIterator. For the purposes of page
clients, this is a contiguous sequence of storage. The buffer iterator provides access to the storage
and conveys the number of bytes in the message. The processStreamSync() method illustrates the
technique for accessing the data. Notice that the buffer indexing is based on one, not zero. This class
uses some simple escape sequences for cursor positioning when printing status messages.
//
// This file contains the implementation of AnsiPageSnapshotClient
//

#include "rtr/rtrnotif.h"// Access to event loop


#include "rtr/rtpgsrv.h"// RTRRTPageService
#include "pagesnapclient.h"

#define CLR_SCRN "\033[2J"


#define STATUS_POSITION "\033[25;1H"

//
// Constructor
//
AnsiPageSnapshotClient::AnsiPageSnapshotClient(
RTRRTPageService& service, const char *symbol)
{ // 1
cout << CLR_SCRN << flush;
_page = &(service.rtPage(symbol));
_page->addClient(*this);
if ( _page->active() )
{
if ( _page->imageAvailable() )
processStreamSync(_page->imageData());
else
processStreamInfo();
}
else
{ // 2
cout << STATUS_POSITION << "Page inactive:" << _page->text() << flush;
_page->dropClient(*this);
_page = 0;
}
}

SFC Developer’s Guide 163


4.4 SFC MODELS

//
// Destructor
//
AnsiPageSnapshotClient::~AnsiPageSnapshotClient()
{
// 3
if ( _page )
_page->dropClient(*this);
}

RTRRTPage *AnsiPageSnapshotClient::page(){return _page;}

//
// Event processing
//
void AnsiPageSnapshotClient::processStreamInactive()
{
cout << STATUS_POSITION << "Page inactive:" << _page->text() << flush;
_page->dropClient(*this);
_page = 0;
}

void AnsiPageSnapshotClient::processStreamInfo()
{
// 4
cout << STATUS_POSITION << "Page info:" << _page->text() << flush;
}

void AnsiPageSnapshotClient::processStreamSync(RTRBufferReadIterator& iter)


{
// 5
cout << iter.to_c(1) << flush;
if ( _page->stale() )
cout << STATUS_POSITION << "Page stale:" << _page->text() << flush;
_page->dropClient(*this);
_page = 0;
RTREventNotifierInit::notifier->disable();
}

SFC Developer’s Guide 164


4.4 SFC MODELS

// 1 Pages should always be accessed in this manner


// * Obtain a reference to the desired page
// * Register a client with the page
// * Test the state of the page
// Services return references to pages, meaning that they are never
// null. However, because clients should not retain references to inactive
// pages, this class stores a pointer to the page. This so that the pointer
// can be set to null in the event of the page being inactive.
//
// 2 Clients should never remain registered with pages in the inactive state
//
// 3 Be sure to un-register clients when clients are destructed
//
// 4 Pages provide informational text about their state.
//
// 5 The page "sync" event occurs when a page has image data available.
// The data is accessed via the given buffer iterator. In this case
// the iterator is used to obtained a pointer to the start of the
// null-terminated data

4.4.7 Example Application — ANSI Page Snapshot


As would be expected, an application (pagesnap.C) which uses the AnsiPageSnapshotClient class is
very similar to that which uses RecordSnapshotClient.
Like RTRDefaultRTRecordService, RTRDefaultRTPageService is an SSL based service which
creates its own SSL session (an instance of RTRSSLDispatcher). The only difference is that it provides
pages instead of records.
//
// This application creates a single instance of a AnsiPageSnapshotClient
// The program accepts two arguments: the name of the service and the symbol
// of the page to retrieve.
//
// This application uses an instance of RTRDefaultRTPageService to
// provide real-time page data. The class RTRDefaultRTPageService is
// a specific implementation of the RTRRTPageService abstraction which
// creates its own SSL session (an instance of RTRSSLDispatcher). It is
// suitable for simple, single service applications such as this one.

SFC Developer’s Guide 165


4.4 SFC MODELS

#include <iostream.h>

#include "rtr/selectni.h"// Defines RTRSelectNotifier


#include "rtr/dfltrtps.h"// Defines RTRDefaultRTPageService
#include "pagesnapclient.h"

int main(int argc, char **argv)


{
if (argc == 3)
{
// 1
RTRDefaultRTPageService service("pageSnapApp", argv[1]);
if ( service.active() )
{
AnsiPageSnapshotClient snap(service, argv[2]);
// 2
RTRSelectNotifier::run();
return 0;
}
else
cerr << "Service error: " << service.text() << endl;
}
else
cerr << "Usage: " << argv[0] << " service symbol " << endl;

return -1;
}

// 1 The first argument of the RTRDefaultRTPageService is the "context id"


// to be used by the service instance. In this case, its the name of the
// application. The second argument is the name of the service and is
// assumed to be the name of a service available via the SSL . Together
// the context id and the name comprise the unique identifier for this servce
// instance which is used for configuration purposes.
//
// 2 This application uses the RTRSelectNotifier as the main loop. It is
// possible to use a different implementation.

SFC Developer’s Guide 166


4.4 SFC MODELS

4.4.8 Example Class — ANSI Page Updates


This example class is similar to AnsiPageSnapshotClient but adds functionality to monitor the updates
from the page of interest. Since the page will be monitored continuously, this class also provides
processing for stale events and recovery.
In addition to the events processed by AnsiPageSnapshotClient, this class processes these events:
• StreamStale
• StreamNotStale
• StreamUpdate

4.4.8.1 Declaration of AnsiPageUpdClient (ansipageupdclient.h)


//
// This file contains the declaration of AnsiPageUpdateClient which
// illustrates the basic techniques for processing page update events. This
// class is designed to print the image of the requested page and then
// monitor that page for updates. Simple ANSI escape sequences are used
// for display purposes.
//
// This class is simlar to AnsiPageSnapshotClient but provides processing
// for all events.
//

#ifndef _ansipageupdclient_h
#define _ansipageupdclient_h

#include "rtr/rtpage.h"// Defines RTRRTPageClient

class AnsiPageUpdateClient :
public virtual RTRRTPageClient
{
public:
// Constructor
AnsiPageUpdateClient(RTRRTPageService&, const char *);

// Destructor
~AnsiPageUpdateClient();

SFC Developer’s Guide 167


4.4 SFC MODELS

// Attributes - fromt RTRRTPageClient


RTRRTPage *page();

// Event processing
void processStreamResync(RTRBufferReadIterator& iter);
// The stream has new image. It may still be stale. Clients should
// check the condition of the stream.

void processStreamSync(RTRBufferReadIterator& iter);


// The stream has an image. It may still be stale. Clients should check
// the condition of the stream.

void processStreamStale();
// The stream data is out-of-date. Stream state information is
// available via text().

void processStreamNotStale();
// The stream is no longer stale.

void processStreamInactive();
// The stream is invalid. Drop all references immediately. Resources
// consumed by the stream will be reclaimed by the service which
// provided it.

void processStreamInfo();
// The stream has new informational text. The state of the
// stream has not changed.

void processStreamUpdate(RTRBufferReadIterator& iter);


// The stream has updated update event processing.

protected:
// Implementation attributes
RTRRTPage *_page;
};

#endif

SFC Developer’s Guide 168


4.4 SFC MODELS

4.4.8.2 Definition of AnsiPageUpdClient (pageupdclient.C)


//
// This file contains the implementation of AnsiPageUpdateClient
//

#include "rtr/rtrnotif.h"// Access to event loop


#include "rtr/rtpgsrv.h"// RTRRTPageService
#include "pageupdclient.h"

#define CLR_SCRN "\033[2J"


#define STATUS_POSITION "\033[25;1H"

// 1

AnsiPageUpdateClient::AnsiPageUpdateClient(
RTRRTPageService& service, const char *symbol)
{
cout << CLR_SCRN << flush;
_page = &(service.rtPage(symbol));
if ( _page->active() )
{
_page->addClient(*this);
if ( _page->imageAvailable() )
processStreamSync(_page->imageData());
}
else
{
cout << STATUS_POSITION << "Page inactive:" << _page->text() << flush;
_page = 0;
}
}

AnsiPageUpdateClient::~AnsiPageUpdateClient()
{
if ( _page )
_page->dropClient(*this);
}

SFC Developer’s Guide 169


4.4 SFC MODELS

RTRRTPage *AnsiPageUpdateClient::page()
{
return _page;
}

void AnsiPageUpdateClient::processStreamResync(RTRBufferReadIterator& iter)


{
// 2
processStreamSync(iter);
}

void AnsiPageUpdateClient::processStreamSync(RTRBufferReadIterator& iter)


{
cout << iter.to_c(1) << flush;
if ( _page->stale() )
processStreamStale();
}

void AnsiPageUpdateClient::processStreamStale()
{
cout << STATUS_POSITION << "Page stale:" << _page->text() << flush;
}

void AnsiPageUpdateClient::processStreamNotStale()
{
cout << STATUS_POSITION << "Page ok:" << _page->text() << flush;
}

void AnsiPageUpdateClient::processStreamInactive()
{
cout << STATUS_POSITION << "Page inactive:" << _page->text() << flush;
_page->dropClient(*this);
_page = 0;
}

void AnsiPageUpdateClient::processStreamInfo()
{
cout << STATUS_POSITION << "Page info:" << _page->text() << flush;
}

SFC Developer’s Guide 170


4.4 SFC MODELS

void AnsiPageUpdateClient::processStreamUpdate(RTRBufferReadIterator& iter)


{
cout << iter.to_c(1) << flush;
}

// 1 It is assumed that the reader is familiar with the AnsiPageSnapshotClient


// example.
//
// 2 Resync events are correspond to unsolicited images. The sync event is
// a solicited event. Resync events are used to update a stale image.

An application which uses the AnsiPageUpdateClient can be found in ansipageupd.C. It is very


similar to the previous example (section 4.4.7).

SFC Developer’s Guide 171


4.5 SFC MODELS

4.5 Time-Series

4.5.1 Overview

4.5.1.1 Time-Series
A time-series represents the historical record of market activity for some financial instrument. The
history includes data for one or more fields of interest, e.g. price or trading volume over some period. A
series is a time-ordered sequence of data samples. Each sample contains the values of the relevant
fields at the point in time represented by the sample.
A periodic series provides samples which occur with a fixed frequency, e.g. daily or weekly, and which
represent a summary of trading activity for the period between two samples. An aperiodic, or tick,
series provides samples which represent actual market activity. The semantics of the two types of
series is different. For example, in a periodic series volume would typically represent accumulated
volume for the period, while in an aperiodic series, volume would represent the volume of a particular
trade. The difference in semantics of the two series manifests itself in the field content of the series.
Samples are the constituent parts of a series. Each has a time-stamp and provides access to its
constituent values. In some circumstances a sample may be invalid, e.g. a sample from a daily series
which falls on a holiday. Each value has an identifier corresponding to that of the field which it
represents. The semantics of the value is determined by the identifier.
Applications need to traverse some or all of the available samples in a series. They may need a fixed
number of samples or all of the samples that fall within a certain time period. A client of a series must
specify the range of samples which is required, i.e., the "view" which it will take. Retrieval of data for a
given view may be synchronous or asynchronous. If asynchronous, a series may be in an incomplete
state for some period of time. Once complete, the series is responsible for informing the client that the
requested view has been established.
The SFC class representing time-series is RTRTimeSeries. Samples are of type RTRTimeSample,
while clients are of type RTRTimeSeriesClient. The time-series client class provides the mechanism by
which a series propagates state change events and informational messages to an interested
application component.

SFC Developer’s Guide 172


4.5 SFC MODELS

NOTE: SFC provides two request types for time-series data model when Reuters disable the
streaming (updating) TS1 capability. The *requestTS1RealTime configurable parameter is provided
for users to change the primary record request behavior to request TS1 data in real-time as
opposed to a snapshot. The default value is False.

4.5.1.2 Time-Series Services


Time-series are created by a time-series service whose responsibility is to shield applications from the
implementation details associated with retrieving time-series data. Time-series services are
descendants of the abstract base class RTRTimeSeriesService.

4.5.1.3 Simple Series


When performing calculations, a simplified view of a time-series provides some convenience. An
RTRSimpleSeries is similar to a time-series but has data for only a single field. It is derived from an
RTRTimeSeries and provides a static representation whose scope is defined by the current view of the
series. Access to data values and error checking are simplified.

4.5.2 Time-Series State Diagram


Time-series state is defined by the values of two series attributes:
• complete
• error
State transitions are propagated to clients as events. Figure 4.16 shows snapshot time-series states
and events causing state transitions.

SFC Developer’s Guide 173


4.5 SFC MODELS

Complete
Complete Incomplete

Error

Error

Complete (error = False, complete = True)


Incomplete (error = False, complete = False)
Error (error = True, complete = XX)

Figure 4.16: Snapshot Time-Series States and Variables

State transitions are propagated to clients as events. Figure 4.17 shows real-time time-serie states and
events causing state transitions. The *requestTS1RealTime configurable option has to be set to True.

SFC Developer’s Guide 174


4.5 SFC MODELS

Complete
Info Complete Incomplete Info
/NewSample
/NewEvent
Error
Error

Error

Complete (error = False, complete = True)


Incomplete (error = False, complete = False)
Error (error = True, complete = XX)

Figure 4.17: Real-Time Time-Series States and Variables

4.5.3 Class Summary


This section provides a summary of the classes which comprise the model for time-series data. For
more details please refer to the appropriate sections of the alphabetical class reference.
• RTRTimeSeries - This class represents the historical data for a given instrument. A time-series is
"owned" by a particular client to whom data and state change events will be propagated. The
scope of the data contained by the series is determined by the client. Series provide random
(indexed) and sequential access to the data samples which comprise the series. The period
(interval between samples) of a time-series is determined when the series is obtained from the
providing service.
• RTRTimeSample - Samples are the constituent parts of a time-series and represent a time-
stamped collection of values. Samples have state (they may be invalid) and provide random and
sequential access to the values they contain.

SFC Developer’s Guide 175


4.5 SFC MODELS

• RTRSeriesValue - Values contain the historical data values for a particular field of interest, e.g.,
trading volume for the interval represented by a sample.
• RTRTimeSeriesClient - This is the abstract base class for application components which can
own a time-series and which will receive events relating to that time-series.
• RTRTimeSeriesService - This is the abstract base class for providers of time-series data.
• RTRSimpleSeries - A series which contains values for only a single field. Instances of this class
are derived from a complete series and are used to provide simplified access to data for a
particular field.
• RTRTSValDefDb - The database of field definitions used by a particular service.
• RTRTSValDefDbClient - This is the abstract base class for application components which need
to know when the RTRTSValDefDb is completely populated and when it updates.
• RTRSeriesValueDefinition - Provides the description for a column in a time-series. A definition
comprises the name, identifier, and type of column. The type determines the way in which the raw
data should be interpreted; the name and identifier define the meaning of the field.

4.5.4 Implementation
Currently, the SFC provides an implementation of the time-series model which relies on the TS1 data
available over the Reuters datafeeds. Other implementations are possible. The TS1 implementation
uses the abstract interface of either the snapshot or real-time (setting *requestTS1RealTime to True)
record model to retrieve the encoded time-series data. While most application components should
refer only to the base classes mentioned in the preceding section, the "main" routine or initialization
section of an application must instantiate one or more implementation specific classes.
Typically, applications will create a single instance of a TS1 time-series service, which is described in
as follows:
• RTRTS1TimeSeriesService - This implementation of RTRTimeSeriesService uses an instance
of RTRRTRecordService to retrieve snapshot records or real-time records (setting
*requestTS1RealTime to True) containing compressed time-series data in the TS1 format. Please
refer to section 4.1.1 for more information on the real-time and snapshot record models and
associated implementation classes. TS1 data may span multiple records and must be
decompressed prior to use. The implementation relies on numerous underlying classes such as
RTRTS1TimeSeries and RTRTS1TimeSample. A complete description of these and related
implementation classes is beyond the scope of this manual.

SFC Developer’s Guide 176


4.5 SFC MODELS

4.5.4.1 Multiple Services


Some applications use more than one service. The connection and service pool factory classes make
it easy to incorporate multiple services in a single application.
RTRSSLConnection and RTRTIBConnection can be used to fine tune the connection parameters for
the implementation record services. They are described in detail in section 4.8.1.
RTRSSLServicePoolFactory and RTRTIBServicePoolFactory can bed used to manage the life-cycle of
and share a single connection among several market data services. They are described in detail in
section 4.8.2

4.5.5 Examples
SFC includes several examples which highlight different parts of the time-series model. All of these
examples can be found the sfc/examples/historical/ directory. These examples typically have two
parts:
1. main() function that:
• parses command line arguments
• creates a service pool factory or record service
• creates a time-series client
• creates the event control loop
2. SFC client implementation that is responsible for
• requesting a time-series
• printing output to standard out
The following table summarized the time-series examples and details where more information about
them can be found.

SFC Developer’s Guide 177


4.5 SFC MODELS

Example Program Description Refer to...

TSDump creates a time-series client to get weekly data a speci- section 4.5.6
fied number of samples tsdump.C
tsbycount.*

TSDates creates a time-series client to get weekly data


between the specified dates tsdates.C
tsbydate.*

TSAvg computes simple average of a specified number of tsavg.C


weekly samples simpleclient.*

Table 4.13: Time-Series Examples

4.5.6 TSDump Example


This section provides an example which illustrates the behavior of a typical time-series client. For
simplicity, its functionality is limited to output. However, it does illustrate the correct way in which to
access time-series data by specializing the RTRTimeSeriesClient abstraction. The functional
requirements for this client are as follows:
• Given a symbol, retrieve the weekly data for that instrument and print some number of weeks
worth of data on the standard output device.
• Print any errors to the standard error device.
• Terminate the application when the data is complete or an error occurs.
To implement these requirements this class must be designed so that:
• It has access to a time-series service. Ideally, this class is not concerned with the implementation
of that service.
• It is a time-series client in order to receive events generated by a time-series.

SFC Developer’s Guide 178


4.5 SFC MODELS

4.5.6.1 Declaration of TSClientByCount (tsbycount.h)


The example header file which follows declares a descendant of RTRTimeSeriesClient called
TSClientByCount. This declaration provides implementations of the pure virtual event-handling
methods which are inherited from RTRTimeSeriesClient. The implementation for this class follows the
declaration.
//
// This file contains the declaration of TSClientByCount which
// illustrates the basic techniques for processing time series events. This
// class is designed to print a number of samples for a single series.
//
// The number of samples printed is an argument to the constructor
//

#ifndef _tsbycount_h
#define _tsbycount_h

#include "rtr/tseries.h"// Defines RTRTimeSeries

class TSClientByCount :
public virtual RTRTimeSeriesClient
{
public:
// Constructor
TSClientByCount(
RTRTimeSeriesService&,// The service to use
const char *, // name of instrument to retrieve
int // the number of samples to retrieve
);

// Event processing - from RTRTimeSeriesClient


void processSeriesComplete(RTRTimeSeries&);
// Process a "complete" event generated by the series.

void processSeriesError(RTRTimeSeries&);
// Process an error event generated by the series.

void processSeriesInfo(RTRTimeSeries&);
// Process an informational event generated by the series.

SFC Developer’s Guide 179


4.5 SFC MODELS

protected:
// Implementation attributes
RTRTimeSeries _series;
};

#endif

4.5.6.2 Definition of TSClientByCount (tsbycount.C)


The correct procedure to use in accessing time-series from a service can be represented in pseudo-
code as follows:
Get time-series
If not time-series error then
If time-series complete then
process time-series complete
else
process time-series error
This is illustrated in the constructor of TSClientByCount.

//
// This file contains the implementation of TSClientByCount.
//
#include "rtr/rtrnotif.h"// Access to event loop
#include "tsbycount.h"
//
// Constructor
//
TSClientByCount::TSClientByCount(
RTRTimeSeriesService& service,
const char *symbol,
int numSamples
)
: _series(service.timeSeries(symbol, RTRTimeSeriesService::Weekly, *this))
// 1
{// 2
// Specify the desired content of the series and check it’s state.
_series.setView(numSamples);

SFC Developer’s Guide 180


4.5 SFC MODELS

if (!_series.error())
{
if (_series.complete())
processSeriesComplete(_series);
else
processSeriesInfo(_series);
}
else
processSeriesError(_series);
}

//
// Event processing
//
void TSClientByCount::processSeriesComplete(RTRTimeSeries&)
{
// 3
cout << _series << endl;
RTREventNotifierInit::notifier->disable();
}

void TSClientByCount::processSeriesError(RTRTimeSeries& s)
{
cerr << s.symbol() << " - Error :" << s.text() << endl;
RTREventNotifierInit::notifier->disable();
}

void TSClientByCount::processSeriesInfo(RTRTimeSeries& s)
{
cerr << s.symbol() << " - Info :" << s.text() << endl;
}

// 1 The series is requested with a symbol (the name of underlying instrument),


// the desired period, and a client.
//
// 2 The constructor illustrates how to access the first ‘n’ samples in
// a time-series.
//
// 3 A ostream operator is used here to dump the RTRTimeSeries.

SFC Developer’s Guide 181


4.5 SFC MODELS

This class by itself does not comprise an application. A complete application must provide access to
an implementation of RTRTimeSeriesService and must instantiate one (or more) instance of
TSClientByCount. The next section illustrates such an application.

4.5.6.3 Example Application — Time-Series


This example application uses an RTRTS1TimeSeriesService, a descendant of
RTRTimeSeriesService which uses TS1 encoded data extracted from snapshot or real-time records.
The program takes three command line arguments: the name of the real-time record service to use (for
TS1 data), the symbol for the record whose history is to be retrieved, and the number of samples to
print.
This is the output of the program:
> -infra ssl -servicename IDN_SELECTFEED -symbol RTRSY.O -n 4
Date CLS OPN HI LOW VOL
11/25/94 44 45.25 45.5 43.75 534800
11/18/94 45.375 44.5 46.125 44.5 1.2441e+06
11/11/94 45.125 46.5 46.75 45 1.0838e+06
11/04/94 47 46.75 48 46.75 2.4099e+06
>
This example only shows how to create a time series using a SSL record service. To run using the TIB
record implementation, change the sslrtrs.h include and the record constructor to the TIB equivalents.
For an example of a single application that can connect to either, see (tsdump.C).
//
// This application creates a single instance of a TSClientByCount
// The program accepts three arguments: the name of the service, the symbol
// of the instrument (e.g. RTRSY.O), and the number of samples to retrieve.
//
// This application uses TS1 based data which is retrieved via an
// implementation of RTRRTRecordService.
//

#include <iostream.h>
#include <stdlib.h>

#include "rtr/selectni.h"// Defines RTRSelectNotifier


#include "rtr/sslrtrs.h"// Defines RTRSSLRTRecordService
#include "rtr/ts1srvc.h"// RTRTS1TimeSeriesService

SFC Developer’s Guide 182


4.5 SFC MODELS

#include "tsbycount.h"

int main(int argc, char **argv)


{
if (argc == 4)
{
// Allocate the real-time record service used by the
// TS1 implementation of RTRTimeSeriesService
// 1
RTRSSLRTRecordService rtService("tsDumpApp", argv[1], "");
if (rtService.active())
{
// Allocate the TS1 based time-series service
RTRTS1TimeSeriesService tsService(rtService, "IDN_TS1");
TSClientByCount client(tsService, argv[2], atoi(argv[3]));
// 2
RTRSelectNotifier::run();
return 0;
}
else
cerr << "Service error:" << rtService.text() << endl;
}
else
cerr << "Usage: " << argv[0] << " service symbol #_of_samples" << endl;
return -1;
}

// 1 A RTRTS1TimeSeriesService needs a RTRRTRecordService from which to request


// its data. This example shows a RTRSSLRTRecordService. A RTRTIBRTRecordService
// could also be used. The first argument of the RTRSSLRTRecordService is the
// "context id" to be used by the service instance. In this case, it is the name
// of the application. The second argument is the name of the service and is
// assumed to be the name of a service available via the SSL . Together
// the context id and the name comprise the unique identifier for this servce
// instance which is used for configuration purposes. The third argument is
// the username. Since the username is "", the host’s login name will be used.
//
// 2 This application uses the RTRSelectNotifier as the main loop. It is
// possible to use a different implementation.

SFC Developer’s Guide 183


4.5 SFC MODELS

4.5.6.4 Example Code — ostream Output Methods


While the TSDump example client illustrates the correct design of a client, it does not provide much
detail on how to access the data contained by the series. The output routine used by the program is a
good example of how to access samples from the series.

NOTES:
• The series provides array style access to its constituent samples.
• The series provides attributes which define the valid range of indices (upper() & lower()).

ostream& operator<<(ostream& os, RTRTimeSeries& series)


{
int hdrdumped = 0;
if (series.count() > 0)
{
for (int i = series.lower(); i <= series.upper(); i++)
{
if (series[i].valid() && !hdrdumped)
{
os.width(8);
os << "Date";
RTRTimeSample& sample = series[series.lower()];
for (int j = sample.lower(); j <= sample.upper(); j++)
{
RTRSeriesValue& value = sample[j];
os.width(12);
os << value.name();
}
os << endl;
hdrdumped = 1;
}
os << series[i];
if (i < series.upper())
os << endl;
}

SFC Developer’s Guide 184


4.5 SFC MODELS

}
return os;
}
Likewise, the output routine used above to print values from a sample illustrates the proper technique
to use when extracting values from a sample:

NOTES:
• Like a series, a sample provides array style access to its constituent values.
• The sample provides attributes which define the valid range of indices (upper() & lower()).

ostream& operator<<(ostream& os, RTRTimeSample& sample)


{
const RTRDateTime& dateTime = sample.dateTime();
os.width(2);
os << dateTime.monthNumber();
os << "/";
os.width(2);
os.fill(‘0’);
os << dateTime.dayOfMonth();
os.fill(‘ ‘);
os << "/";
os << dateTime.year() - 1900;
if (sample.valid())
{
for (int i = sample.lower(); i <= sample.upper(); i++)
{
os.width(12);
os << sample[i];
}
}
else
os << " :" << sample.text();
return os;
}
And lastly, the value output routine is as follows:

SFC Developer’s Guide 185


4.5 SFC MODELS

NOTES:
• Access to the floating point representation of a value is only meaningful if the value is "valid".
• A value provides an operator which allows the application to cast the value as a floating point
number (in this case, the explicit cast is required).

ostream& operator<<(ostream& os, const RTRSeriesValue& value)


{
if (value.valid())
os << (float)value;
else
os << value.text();
return os;
}

4.5.7 TSDates Example


This section illustrates how to implement a time-series client which extracts time-series data by date,
rather than just using some number of the most recent samples. The new class is similar to
TSClientByCount except that is takes two strings on the constructor rather than the integer value
corresponding to the number of samples. These strings are dates using MM/DD/YYYY format.

4.5.7.1 Declaration of TSClientByDate (tsbydate.h)


//
// This file contains the declaration of TSClientByDate which
// illustrates the basic techniques for processing time series events. This
// class is designed to print a number of samples for a single series.
//
// The number of samples printed is determined by dates (as formatted
// strings) passed to the constructor. Start dates are more recent than
// end dates.
//

#ifndef _tsbycount_h
#define _tsbycount_h

SFC Developer’s Guide 186


4.5 SFC MODELS

#include "rtr/tseries.h"// Defines RTRTimeSeries

class TSClientByDate :
public virtual RTRTimeSeriesClient
{
public:
// Constructor
TSClientByDate(
RTRTimeSeriesService&,// The service to use
const char *, // name of instrument to retrieve
const char *, // string representing desired start date
const char * // string representing desired end date
);

// Event processing - from RTRTimeSeriesClient


void processSeriesComplete(RTRTimeSeries&);
// Process a "complete" event generated by the series.

void processSeriesError(RTRTimeSeries&);
// Process an error event generated by the series.

void processSeriesInfo(RTRTimeSeries&);
// Process an informational event generated by the series.

protected:
// Implementation attributes
RTRTimeSeries _series;
};

#endif

4.5.7.2 Definition of TSClientByDate (tsbydate.C)


The date strings are passed to the setView() method of RTRTimeSeries. This method takes two
arguments of type RTRVariableDateTIme. Strings can be used because that class provides a
constructor using strings in the required format. The use of strings in this context results in the creation
of a temporary object(s). The programmer can, of course, provide date objects instead of strings.
// The definition of TSClientByDate.

SFC Developer’s Guide 187


4.5 SFC MODELS

//

// 1

#include "rtr/rtrnotif.h"

#include "tsbydate.h"

//
// Constructor
//
TSClientByDate::TSClientByDate(
RTRTimeSeriesService& service,
const char *symbol,
const char *startDate,
const char *endDate
)
: _series(service.timeSeries(symbol, RTRTimeSeriesService::Weekly, *this))
{
// 2
_series.setView(startDate, endDate);
if (!_series.error())
{
if (_series.complete())
processSeriesComplete(_series);
else
processSeriesInfo(_series);
}
else
processSeriesError(_series);
}

//
// Event processing
//
void TSClientByDate::processSeriesComplete(RTRTimeSeries&)
{
cout << _series << endl;
RTREventNotifierInit::notifier->disable();
}

SFC Developer’s Guide 188


4.5 SFC MODELS

void TSClientByDate::processSeriesError(RTRTimeSeries& s)
{
cerr << s.symbol() << " - Error :" << s.text() << endl;
RTREventNotifierInit::notifier->disable();
}

void TSClientByDate::processSeriesInfo(RTRTimeSeries& s)
{
cerr << s.symbol() << " - Info :" << s.text() << endl;
}

// 1 This class is similar in most respects to the TSClientByCount class


// of the previous example.
//
// 2 Here, the content of the series is specified by date, rather than by
// count. The setView() method of RTRTimeSeries accepts objects of type
// RTRVariableDateTime. Here, the arguments are of type const char *
// which cause the compiler to generate temporary variables of type
// RTRVariableDateTime, using the appropriate constructor.

The rest of the client implementation stays the same. Obviously, the application (tsdates.C) which
uses this client is slightly different from the original application because it must provide two dates.
A modified version of the original application is required. It takes two string arguments instead of the
integer. The original version extracted four weeks of data. The data for the same four weeks of the
preceding year can be extracted using tsdates as follows:
> -infra ssl -servicename IDN_SELECTFEED -symbol RTRSY.O -d1 11/30/1993 -d2
11/01/1993
Date OPN CLS HI LOW VOL
11/26/93 36.125 35.25 36.1875 34.875 2.0072e+06
11/19/93 34.9375 36.5625 36.75 34 5.2614e+06
11/12/93 36.5625 36.125 37.125 35.9375 2.6146e+06
11/05/93 36.4375 36.4375 37.375 35.75 1.941e+06

4.5.8 TSAvg Example


As an example, suppose the requirement is to compute the n week simple average of some field from
a time-series. The class which implements this is similar to TSClientByCount but takes an extra

SFC Developer’s Guide 189


4.5 SFC MODELS

argument (in addition to the service, symbol, and number of samples arguments) to the constructor
which specifies the name of the field on which to perform the computation.

4.5.8.1 Declaration of SimpleSeriesClient (simpleclient.h)


//
// This file contains the declaration of SimpleSeriesClient which
// illustrates how to access a RTRSimpleSeries from an RTRTimeSeries.
// A simple series contains the data for just one field from the original
// series.
//
// The data is used to calculate an average.
//
// The number of samples printed is an argument to the constructor. The
// field which is retrieved is also a constructor argument.
//

#ifndef _simpleclient_h
#define _simpleclient_h

#include "rtr/tseries.h"// Defines RTRTimeSeries

class SimpleSeriesClient :
public virtual RTRTimeSeriesClient
{
public:
// Constructor
SimpleSeriesClient(
RTRTimeSeriesService&,// the service to use
const char *, // name of instrument to retrieve
int, // the number of samples to retrieve
const char * // name of the field to retrieve
);

// Event processing - from RTRTimeSeriesClient


void processSeriesComplete(RTRTimeSeries&);
// Process a "complete" event generated by the series.

void processSeriesError(RTRTimeSeries&);
// Process an error event generated by the series.

SFC Developer’s Guide 190


4.5 SFC MODELS

protected:
// Implementation attributes
RTRTimeSeries _series;
RTRString _fieldName;
};

#endif

4.5.8.2 Definition of SimpleSeriesClient (simpleclient.C)


The processSeriesComplete() method illustrates the technique for accessing a simple series.
//
// This file contains the implementation of SimpleSeriesClient.
//

#include "rtr/rtrnotif.h"
#include "simpleclient.h"

SimpleSeriesClient::SimpleSeriesClient(
RTRTimeSeriesService& service,
const char *symbol,
int numSamples,
const char *fieldName
)
: _series(service.timeSeries(symbol, RTRTimeSeriesService::Weekly, *this)),
_fieldName(fieldName)
{
_series.setView(numSamples);
if (!_series.error())
{
if (_series.complete())
processSeriesComplete(_series);
}
else
processSeriesError(_series);
}

SFC Developer’s Guide 191


4.5 SFC MODELS

void SimpleSeriesClient::processSeriesComplete(RTRTimeSeries&)
{
RTRSimpleSeries ss = _series.simpleSeries(_fieldName, _fieldName);
float sum = 0;
int n = 0;
for (int i = ss.lower(); i <= ss.upper(); i++)
{
if (ss[i].valid())
sum += (float)ss[i];
n++;
}
if (n)
cout << "Average is : " << sum/n << endl;
else
cout << "No valid data" << endl;
RTREventNotifierInit::notifier->disable();
}

void SimpleSeriesClient::processSeriesError(RTRTimeSeries& s)
{
cerr << "Error - " << s.symbol() << ":" << s.text() << endl;
RTREventNotifierInit::notifier->disable();
}

An application called tsavg uses the new class and produces the following output:
> -infra ssl -servicename IDN_SELECTFEED -symbol RTRSY.O -n 3 -field vol
Average is : 954233
>

SFC Developer’s Guide 192


4.6 SFC MODELS

4.6 Inserts
NOTE: The insert model can only be used to contribute data to Triarch and RMDS. See section
5.5.9 for details on how to contribute on an RTIC-based RMDS infrastructure.

4.6.1 Overview
An insert is used to pass information related to a particular market data item to a service associated
with that item. An insert is passed to an insert service, where the insert may be accepted or denied.
An insert transaction starts when an insert is passed to an insert service and ends when the service
accepts or rejects the insert. An insert client is the application component that is notified at the
completion of an insert transaction.
The format and content of the information provided in an insert is service specific. Therefore, an
application utilizing inserts must know how to format information for each insert service. Typically this
format is Marketfeed. See the Reuters Marketfeed Reference Manual for details on the Marketfeed
data format.

4.6.2 Insert Items


An RTRInsert is an abstract class that provides the functions needed to start an insert transaction. In
particular, there are functions used to set the name of a market data item and to format the data that
will be inserted for that item. Other functions are available to access information associated with the
insert transaction. For example, the unique identifier and descriptive text can be set and accessed for
each insert.
An RTRInsertClient has the ability to receive notifications regarding the completion of an insert
transaction. An insert client is notified the success or failure of the transaction.
An insert transaction starts when an application component obtains a new insert object from an insert
service via the newInsert() function of the RTRInsertService object. Note that an insert can have only
one client, so a reference to a descendant of RTRInsertClient is passed the newInsert() call. Calling
the removeInsert() function, on the other hand, will remove the insert.
The application component is responsible for setting the item name and data portions of the insert
object to the appropriate values. The insert’s write() function is invoked to submit the insert. When the
transaction is completed, the insert client is notified asynchronously that the insert transaction has
ended and that the insert information was either accepted or rejected by the insert service.

SFC Developer’s Guide 193


4.6 SFC MODELS

Note that upon completion of the transaction, all references to the insert must be released so that the
insert object may be freed by the insert service.

4.6.3 Insert Services


The RTRInsert instance is obtained from a descendant of an RTRInsertService. The insert service
provides functions to create and return a new insert object and to access the current state of the
service. An insert service may transition between two states: stale and not stale. An insert service that
is not stale can create new instances of RTRInsert and process new insert transactions. A stale insert
service will complete any outstanding insert transactions, but will not accept any new ones.
An RTRInsertServiceClient has the ability to receive notifications regarding transitions in the state of
an insert service.

4.6.3.1 Insert Service Pools


An insert service may be obtained from an instance of RTRDefaultInsertServicePool.

4.6.4 Insert Request Server1


An insert server may repond to an insert publisher with acknowledgement on each insert received.
This is only valid for an SSL insert server on the Market Data Hub. Insert publishers can be on either
RMDS or SSL infrastructure. When receiving an insert from an insert publisher downstream, the insert
server can indicateInsertSucceeded() or indicateInsertFailed() to the insert publisher. The insert
server receives a request for the insert through RTRInsertRequest. The RTRInsertRequest contains
the insert object and the methods for acknowledgement.
The implementation of the insert server is done on the RTRRTRecordServiceImplClient interface.
The insert request server will receive an event called
processInsertRequest(RTRInsertRequest&).The RTRInsertRequest object contains the methods
for the insert request server to send acknowledgements. The default implementation for this event is
sending an indicateInsertFailed() to the insert publisher.
When sending an indicateInsertFailed(), application may set the failure text by using setText2

1. Publishers are able to receive inserts; subscription clients are able to publish out inserts. In this section, ’insert pub-
lisher’ is the subscription client. the ’insert request server’ is the publisher that is able to respond to inserts.

2. The setText method limits text length to 80 characters; the exceeded characters will be truncated.

SFC Developer’s Guide 194


4.6 SFC MODELS

method. It may also set the failure code by using setNakCode method. See Reference Manual for
more details.
If the default implementation is overriden, the insert request server must make sure to send
acknowledgements in a timely fashion for the following reason. For each insert received, it is added to
a list. When the insert request server sends a success or failure for an insert, that particular insert is
then removed from the list and deleted. If the insert request server never sends success or failure for
that insert, this insert will only be removed and deleted when the service is marked stale, at which time
a failure for that insert will be sent.
A constraint for this insert request server is that if it never sends success or failure on a insert, the
insert request server’s cache has the potential of running out of RAM; each insert received is put into
the list. The insert request server application must keep track of inserts at all times.

4.6.5 Example Class — Insert Server


This program will create a publishing service that sends an acknowledgement back to the insert
sender whenever it receives an insert. This program is based on example program Simulator. See the
Simulator example for more detailed description of a publishing application. This section will only
explain how to implement the methods necessary to ensure inserts are received and
acknowledgements are sent.

4.6.5.1 Creating an Application


This section is the same as that for the Simulator example (see section 4.2.6.8). The insert request
server is only supported on the Market Data Hub; therefore, the -pubinfra option must be set to "ssl" to
run this application.
Header file
...See Simulator code for simsrvc.h ...
// along with processNewRecord(RTRRTRecordServiceImpl&, RTRRTRecordImpl&)
// Insert Request Server need to implement the
// processInsertRequest(RTRInsertRequest) method.

// ... continue from Simulator code

// inherited from RTRRTRecordServiceImplClient


void processInsertRequest(RTRInsertRequest&);

Source file

SFC Developer’s Guide 195


4.6 SFC MODELS

...See Simulator code for simsrvc.C ...


// ... continue from Simultor code
void SimpleInsertReply::processInsertRequest(RTRInsertRequest& request)
{
if (request.length()>0)
request.indicateInsertSucceeded();
else
request.indicateInsertFailed();
}

4.6.5.2 Example Class — Insert Client


This program will create an RTRDefaultInsertServicePool, create an RTRInsertService instance, wait
for the service to become synchronized (not stale), then do one insert transaction and exit. Text is
printed out to describe each action as it occurs.
The header file siminsrt.h contains the definition for class SimpleInsertExample. This class inherits
from RTRInsertServiceClient and RTRInsertClient so it can receive event notifications from instances
of RTRInsertService and RTRInsert. SimpleInsertExample takes at construction a reference to an
insert service, the name of a data item, and insert data formatted into a string.
The function sendInsert() handles the task of obtaining an insert object, filling in the item name and
data portions of the insert, and sending the insert to the insert service.
At construction, the program determines whether the service is stale or not. If the service is not stale,
the insert is immediately formatted and sent. Otherwise this class becomes a client of the insert
service so it can be notified when the service becomes not stale. Note that the service’s addClient()
function is called to register interest in notifications for this insert service client. The dropClient()
function is called to drop interest.
The insert object provides a buffer write iterator that is used to set the insert’s data.

4.6.5.3 Declaration for SimpleInsertExample (siminsrt.h)


#include "rtr/rtrdefs.h"
#include "rtr/sslinsrt.h"
#include "rtr/insrtcli.h"
#include "rtr/insrtscl.h"
#include "rtr/rtstring.h"

SFC Developer’s Guide 196


4.6 SFC MODELS

class SimpleInsertExample
: public RTRInsertServiceClient,
public RTRInsertClient
{
protected:

RTRInsertService& _service;
RTRString _itemName;
RTRString _insertData;
void releaseResources();

public:

// Constructor

SimpleInsertExample(RTRInsertService& service, RTRString& itemName,


RTRString& data);
// Create an insert example that uses the given insert service
// to send an insert to the given name with the given data.

// Destructor

virtual ~SimpleInsertExample();

void sendInsert();
// Send an insert and wait for a response.

// Inherited from RTRInsertServiceClient

void processServiceSync(RTRInsertService& srvc);


// The given service is capable of processing inserts.

void processServiceStale(RTRInsertService& srvc);


// The given service is temporarily unable to process inserts.

void processServiceInfo(RTRInsertService& srvc);


// New descriptive text is available for the given service.

// Inherited from RTRInsertClient

SFC Developer’s Guide 197


4.6 SFC MODELS

void processInsertSucceeded(RTRInsert& insert);


// The given insert request succeeded.

void processInsertFailed(RTRInsert& insert);


// The given insert request failed.

};

4.6.5.4 Definition for SimpleInsertExample (siminsrt.C)


#include <iostream.h>
#include "simple.h"
#include "rtr/selectni.h"
#include "rtr/dfltispl.h"
#include "rtr/objid.h"
#include "rtr/rtxfdb.h"

SimpleInsertExample::SimpleInsertExample(RTRInsertService& service, RTRString&


itemName, RTRString& data)
: _service(service),
_itemName(itemName),
_insertData(data)
{
// If the given service is already synchronized, send the insert.
// Otherwise add this instance as a client of the service so
// a notification can be received when the service becomes
// synchronized.
if (!service.stale())
{
cout<<"Service "<<_service.name()<<" is ok."<<endl<<endl;
sendInsert();
}
else
{
cout<<"Service "<<_service.name()<<" stale. Waiting...";
cout<<endl<<endl;
service.addClient(*this);
}
};

SFC Developer’s Guide 198


4.6 SFC MODELS

SimpleInsertExample::~SimpleInsertExample(){;};

void SimpleInsertExample::sendInsert()
{
cout<<"Sending insert for item "<<_itemName<<" and data "<<_insertData;
cout<<" to service "<<_service.name()<<endl<<endl;

// Obtain an insert from the service and


// fill in the item name.
//
RTRInsert& insert = *(_service.newInsert(*this));
insert.setItemName(_itemName);

// Set the insert data. Note that this is a simple example


// that sets the data to a string value. The buffer write
// iterator provides functions to write formatted data,
// like Marketfeed, into the buffer.
//
RTRBufferWriteIterator it = insert.dataWriteIterator();
it.appendString(_insertData);
it.writingCompleted();

// Write the insert to the service. Notification


// regarding the success or failure of the insert
// transaction comes via callback to the processInsertSucceeded()
// or processInsertFailed() functions inherited into
// this class from RTRInsertClient.
//
insert.write();
};

void SimpleInsertExample::processServiceSync(RTRInsertService& srvc)


// The given service is capable of processing inserts.
{
cout<<"Service "<<srvc.name()<<" is now OK. Doing insert"<<endl<<endl;

// Drop as a client of this service and send the insert


// now that the service is active.

SFC Developer’s Guide 199


4.6 SFC MODELS

srvc.dropClient(*this);
sendInsert();
};

void SimpleInsertExample::processServiceStale(RTRInsertService& srvc)


// The given service is temporarily unable to process inserts.
{
cout<<"Service "<<srvc.name()<<" is now STALE."<<endl<<endl;
cout<<"Service Text: "<<srvc.text()<<endl;
};

void SimpleInsertExample::processServiceInfo(RTRInsertService& srvc)


// New descriptive text is available for the given service.
{
cout<<"Service "<<srvc.name()<<" has new INFO."<<endl<<endl;
cout<<"Service Text: "<<srvc.text()<<endl;
};

void SimpleInsertExample::processInsertSucceeded(RTRInsert& insert)


// The given insert request succeeded.
{
cout<<"The insert for item "<<insert.itemName()<<" succeeded."<<endl;
cout<<"Text: "<<insert.text()<<endl<<endl;
cout<<"TEST COMPLETE"<<endl;

releaseResources();
};

void SimpleInsertExample::processInsertFailed(RTRInsert& insert)


// The given insert request failed.
{
cout<<"The insert for item "<<insert.itemName()<<" failed."<<endl<<endl;
cout<<"Text: "<<insert.text()<<endl;
cout<<"TEST COMPLETE"<<endl;

releaseResources();
};

void SimpleInsertExample::releaseResources()
{

SFC Developer’s Guide 200


4.6 SFC MODELS

// For the purposes of this example, just do nothing.


};

4.6.6 Example Application — Inserts


The application setup (in simpleinsert.C) includes the following
#include "siminsrt.h"
#include "rtr/selectni.h"// RTRSelectNotifier
#include "rtr/tsaisrvc.h"// RTRTSAInsertService
#include "rtr/sslinsrt.h"// RTRSSLInsertService

RTRObjectId appId("SimpleInsert");
RTRInsertService *insertService = 0;
void cleanup(int, char * = 0);
void setup(int, char **);
void createLogger(int, char **);
RTRString infra, servicename, symbol, servicePort, daemon, network, value;

int main(int argc, char **argv)


{
// Parse the command line arguments and create a configDb
setup(argc, argv);
// Create a logger.
createLogger(argc, argv);

// Select which architecture to consume from


if (infra == "tsa")
{
insertService = new RTRTSAInsertService(appId, servicename servicePort,
network, daemon);
}
else if (infra == "ssl")
{
insertService = new RTRSSLInsertService(appId, servicename, "");
}
else
cleanup(-1, argv[0]);

// value is the data to insert


SimpleInsertExample example(*insertService, symbol, value);

SFC Developer’s Guide 201


4.6 SFC MODELS

RTRSelectNotifier::run();

cleanup(0, argv[0]);
return 0;
}

SFC Developer’s Guide 202


4.7 SFC MODELS

4.7 Session
NOTE: The session model is independent of infrastructure. It does not use Rrendezvous or
Triarch.

4.7.1 Message Session

4.7.1.1 The Model


Applications that need to communicate with other application processes may utilize a wide variety of
communication protocols and their associated utilities (e.g. TCP/IP, UDP/IP, NETBIOS, WinSock, etc.).
Each of these protocols and associated utilities provide benefits to an application given constraints of
machine type, network type or specific application requirements.
While the capabilities provided by these protocols are quite similar, the programming interfaces used
to access them are not. Changing from one protocol to another in a user application typically means
substantial changes in application code. Most applications that utilize inter-process communications
would benefit from being able to use the same interface for passing messages between peers.
An object oriented analysis of this problem domain yields the concept of a message session, which
has the following characteristics:
• A message session provides message based communication between two peer components.
• A message session transmits messages reliably. Messages are checked for errors and will not be
lost.
• A message session preserves message boundaries. Messages received from a peer have the
same size as when they are sent since message fragmentation and re-assembly is handled by
the message session.
• A message session has a single client that receives asynchronous event notifications. In
particular, a message session client is notified whenever a new message becomes available and
whenever the state of the message session changes.
• A message session is established and may eventually be terminated.
• A message session is uniquely identified from other sessions.
The message session cluster contains classes that encapsulate these characteristics. The main
benefits of using the SFC message session classes is they:

SFC Developer’s Guide 203


4.7 SFC MODELS

• provide one simple interface (RTRMessageSession) for exchanging messages between two peer
application components,
• provide implementation classes of the abstract interface that utilize particular communication
protocols and shield the user from the intricacies of learning how to code to these protocols
interfaces.
The abstract message session interface defines the message exchange portion of peer-to-peer
communication while the specific implementation classes, like a TCP Client Session, define and
implement the abstract interface by using a particular communication protocol and determine how a
message session is created and how associations are made to a peer application component.

4.7.1.2 Message Session Abstraction


The RTRMessageSession class provides an abstract interface that allows application components to
send and receive messages.
Messages are sent to a peer by allocating a message and obtaining a message write iterator of type
RTRMessageWriteIterator that is used to format a message. The iterator’s send() function is called to
send the message to the peer session. If an outgoing message cannot immediately be sent to the
peer, the sending session queues the message and sends it when the peer is able to accept more
messages. The session can queue all the messages that the session can allocate.
Messages received from a peer are obtained from the message session by calling the session’s
lastMessageReceived() function which returns a message read iterator of type
RTRMessageReadIterator. The message read iterator provides functions to access message data as
different sized numerics and as variable sized strings. The user will always receive a full message as
sent by the peer session, since fragmentation and reassembly of a message is handled by the
message session.
A descendant of RTRMessageSessionClient receives asynchronous event notifications from a
RTRMessageSession instance whenever a new message is available from its peer and whenever the
state of the session has changed. A message session will have one and only one client.
The connected() method indicates whether the session is currently connected to its peer. The
RTRMessageSessionClient is notified when the peer connection is lost and must release all session
references.

SFC Developer’s Guide 204


4.7 SFC MODELS

4.7.2 Example — Simple Message Session Clients


The next two sections provide a pair of examples which illustrate the behaviour of typical programs
that use message sessions to communicate with each other. In particular, these sections illustrate how
to implement a message session client, how to read messages from the message session, and how to
write messages to the message session. For simplification, the output of the classes is limited to
printing on the standard output device.

4.7.2.1 Basic Requirements for Reply Class


The hypothetical functional requirements for this client are as follows:
• An instance of this class is a message session client and receives events whenever a new
message is available for reading and when the state of the message session becomes
disconnected.
• An instance of this class waits to receive a message from its peer via the message session.
• The expected message contains the string "HELLO. ARE YOU THERE?" and a message
number.
• Upon receiving a message from the peer, the message information is printed and a reply
message is formatted and sent to its peer via the message session. The reply message contains
the string "YES. I AM HERE?" and the message number received from the peer.
• When the session’s peer disconnects, it causes the message session to indicate that the
message session has become disconnected. The message session and this class instance are
then terminated.
To implement these requirements, this class must be designed so that:
• It is given a reference to a message session.
• It is a message session client so it can be notified whenever a message is available and
whenever the session state changes.
• It cleans up properly after the peer terminates communications.
The example header file which follows declares a descendant of RTRMessageSessionClient called
Reply. RTRMessageSessionClient declares several pure virtual methods which must be implemented
by descendants. The Reply class declares implementations of these methods, which are:
processSessionMessage(), processSessionDisconnected(), and
processSessionAllocationReady().

SFC Developer’s Guide 205


4.7 SFC MODELS

The implementation for this class follows the declaration. It illustrates the correct procedure to use in
reading and writing messages with a message session. In pseudo-code, the procedure for writing a
message is:
Allocate message from message session
If message available from session then
Get a write iterator for the allocated message
Format data into the message
Send the message
else
Wait for allocation ready event from message session or take other action
In pseudo-code, the procedure for reading a message when the processSessionMessage() function
is called is:
Obtain from message session a read iterator to the new message
Use the iterator methods to extract message information

4.7.2.2 Declaration for Reply (reply.h)


#ifndef _reply_h
#define _reply_h

#include "rtr/rtrdefs.h"
#include "rtr/msgsess.h"// Message session

class Reply
: public virtual RTRMessageSessionClient
{
public:
// Constructor
Reply();

// Destructor
virtual ~Reply();

// From RTRMessageSessionClient
void processSessionMessage(RTRMessageSession& session);
// This method is invoked when a new message has been
// received from the session. The method

SFC Developer’s Guide 206


4.7 SFC MODELS

// session.lastMessageReceived() is invoked to retrieve


// the message.

void processSessionDisconnected(RTRMessageSession& session);


// This method is invoked when the session becomes
// disconnected from its peer. This is a permanent
// condition and requires that the session resources
// be cleaned up.

void processSessionAllocationReady(RTRMessageSession& session);


// This method is invoked when the session is again
// capable of allocating messages after a
// session.allocateMessage() call had failed.

// Locally introduced method(s)


void setSession(RTRMessageSession* session);
// Set the message session used for peer communication.

RTRBOOL hasSession();
// Is a session set for this instance?

protected:
void sendReply();
// Format and send the reply message "YES. I AM HERE"
// to the given peer session.

void releaseResources();
// Release all resources held by this instance.

RTRMessageSession *_session; // Session for communication.


static RTRString responseString; // String sent in reply message.
u_16 _messageCount; // Last message count received.
};

#endif // _reply_h

4.7.2.3 Definition for Reply (reply.C)


#include <iostream.h>

SFC Developer’s Guide 207


4.7 SFC MODELS

#include "reply.h"

Reply::Reply()
: _session(0)
{
};

Reply::~Reply()
{
releaseResources();
};

void Reply::processSessionMessage(RTRMessageSession& session)


{
// Get an iterator to the message just received.
RTRMessageReadIterator msg = session.lastMessageReceived();

// Set message iterator to start of message.


msg.start();

// Parse out the length field for the string part.


u_32 _stringPartLength = msg.getUnsigned32();

// Move read cursor to next message element.


msg.forth();

// Parse out the string part.


RTRString tmpStr = msg.getString( _stringPartLength );
msg.forth();

// Parse out the message count.


_messageCount = msg.getUnsigned16();

cout<<"Reply: Got message "<<_messageCount<<" from peer ";


cout<<session.name()<<": \""<<tmpStr<<"\""<<endl;

// Send a reply containing the message count received from the


// requestor.
sendReply();
};

SFC Developer’s Guide 208


4.7 SFC MODELS

void Reply::processSessionDisconnected(RTRMessageSession& session)


{
// Session is no longer viable. This is a permanant condition,
// so release resources and delete this instance.
cout<<"Reply: Session "<<session.name();
cout<<" has DISCONNECTED. Terminating this Reply instance."<<endl;
delete this;
};

void Reply::processSessionAllocationReady(RTRMessageSession& session)


{
// Message may be allocated again, so attempt to
// send the reply message.
cout<<"Reply: Session "<<session.name()<<" ready for writing."<<endl;
sendReply();
};

void Reply::setSession(RTRMessageSession* session)


{
RTPRECONDITION( !hasSession() );
_session = session;
};

RTRBOOL Reply::hasSession()
{
return _session != 0 ? RTRTRUE : RTRFALSE;
};

void Reply::sendReply()
{
// Allocate a new message write buffer.
_session->allocateMessage();

// Check if allocation succeeded.


if (_session->isMessageAllocated())
{
// Get a write iterator to the message buffer.
RTRMessageWriteIterator msg = _session->lastAllocatedMessage();

SFC Developer’s Guide 209


4.7 SFC MODELS

// Format the string part length.


msg.appendUnsigned32(responseString.count());

// Format the string part.


msg.appendString(responseString);

// Format the message count


msg.appendUnsigned16(_messageCount);

// Send the message to the peer requestor.


msg.send();
if (_session->connected())
{
cout<<"Reply: Sending reply to session ";
cout<<_session->name()<<endl<<endl;
}
else
processSessionDisconnected(*_session);
}
else
// The processSessionAllocationReady() method will be
// invoked by the message session when more messages
// can be sent.
cout<<"Reply: Unable to send message! Waiting..."<<endl;
};

void Reply::releaseResources()
{
// Delete the session.
if (_session != 0)
{
_session->terminate();
_session = 0;
}
};

RTRString Reply::responseString = RTRString("YES. I AM HERE.");

SFC Developer’s Guide 210


4.7 SFC MODELS

4.7.3 Example — Another Simple Message Session Client


The class described in this section is the sender of the messages expected by the Reply class. This
class is also a message session client and has the following functional requirements:
• An instance of this class has a message session that is used to send request messages to a peer
Reply instance.
• A message containing the string "HELLO. ARE YOU THERE?" and a message count are
formatted and sent to the peer via the message session.
• An instance of this class then waits for a reply message. Upon receiving a message from the
peer, the message information is printed and a timer is set to go off in 5 seconds.
• When the timer goes off, another message is sent to the peer.
• When a reply with a message count value of 10 is received, the message session and this class
instance are terminated.
To implement these requirements, this class must be designed so that:
• It is given a reference to a message session.
• It is a message session client so it can be notified whenever a message is available and
whenever the session changes state.
• It cleans up properly after it receives the tenth message.
• It inherits from timer command in order to do timing
The following example header file request.h is similar to the reply.h header file in that it declares a
descendant of RTRMessageSessionClient and then declares implementations of the pure virtual
methods inherited from RTRMessageSessionClient. However, this class (called Request) class also
inherits from the RTRTimerCmd class. The RTRTimerCmd class provides methods to set timing
events and a pure virtual method that is invoked when the timer expires. The implementation for this
class follows the declaration.

4.7.3.1 Declaration for Request (request.h)


#include "rtr/rtrdefs.h"
#include "rtr/rtstring.h"
#include "rtr/msgsess.h"
#include "rtr/tcpssvr.h"

SFC Developer’s Guide 211


4.7 SFC MODELS

class Request
: public virtual RTRMessageSessionClient,
public virtual RTRTimerCmd
{
public:
// Constructor
Request();

// Destructor
virtual ~Request();

// From RTRMessageSessionClient
void processSessionMessage(RTRMessageSession& session);
// This method is invoked when a new message has been
// received from the session. The method
// session.lastMessageReceived() is invoked to retrieve
// the message.

void processSessionDisconnected(RTRMessageSession& session);


// This method is invoked when the session becomes
// disconnected from its peer. This is a permanent
// condition and requires that the session resources
// be cleaned up.

void processSessionAllocationReady(RTRMessageSession&);
// This method is invoked when the session is again
// capable of provided messages after a
// session.allocateMessage() call had failed.

// From RTRTimerCmd
void processTimerEvent();
// This method is invoked when the timer goes off.

// Locally introduced method(s)


void setSession(RTRMessageSession* s);
// This class also writes messages to its peer and
// needs access to the message session. This method
// sets the message session, which is then owned by

SFC Developer’s Guide 212


4.7 SFC MODELS

// this instance.
// REQUIRE: !hasSession()

RTRBOOL hasSession();
// Is a session set for this instance?

void start();
// Start sending request messages.
// REQUIRE: hasSession()

protected:

void sendRequest();
// Start sending request messages.

void activateTimer();
// Activate the timer to go off in 5 seconds.

void releaseResources();
// Release all resources held by this instance.

RTRMessageSession *_session; // Session for communication.


static RTRString _requestString; // String sent in request message.
u_16 _messageCount;// Current number of messages sent.

};

#endif //_request_h

4.7.3.2 Definition for Request (request.C)


#include <iostream.h>
#include "rtr/selectni.h" // Notifier
#include "rtr/tcpcsess.h" // Tcp client session
#include "rtr/tcpidimp.h" // Socket identifier
#include "request.h" // Request

Request::Request()
: RTRTimerCmd(),

SFC Developer’s Guide 213


4.7 SFC MODELS

_session(0),
_messageCount(1)
{
};

Request::~Request()
{
releaseResources();
};

void Request::processSessionMessage(RTRMessageSession& session)


{
// Get an iterator to the message just received.
RTRMessageReadIterator msg = session.lastMessageReceived();

// Set message iterator to start of message.


msg.start();

// Parse out the length field for the string part.


u_32 _stringPartLength = msg.getUnsigned32();

// Move read cursor to next message element.


msg.forth();

// Parse out the string part.


RTRString tmpStr = msg.getString( _stringPartLength );
msg.forth();

// Parse out the message count.


u_16 _returnCount = msg.getUnsigned16();

// Print a message to standard output device.


cout<<"Requestor: Got response message "<<_returnCount;
cout<<" from peer "<<session.name()<<": \""<<tmpStr;
cout<<"\". Waiting 5 seconds..."<<endl<<endl;

// Terminate when the tenth response is received.


if (_returnCount >= 10)
{
cout<<endl<<"Requestor: Received tenth reply. Terminating."<<endl;

SFC Developer’s Guide 214


4.7 SFC MODELS

delete this;
}
// Otherwise activate the timer to send another message in 5 seconds.
else
activateTimer();
};

void Request::processSessionDisconnected(RTRMessageSession& session)


{
// Session is no longer viable. This is a permanant condition,
// so release resources and delete this instance.
cout<<"Requestor: Session "<<session.name();
cout<<" is DISCONNECTED. Deactivating now."<<endl;
delete this;
};

void Request::processSessionAllocationReady(RTRMessageSession&)
{
// Messagess are now available, so attempt to send the
// request message.
sendRequest();
};

void Request::processTimerEvent()
{
// The 5 second timer has expired. Send another request message.
sendRequest()
};

void Request::setSession(RTRMessageSession* s)
{
// Precondition enforces the fact that the session
// for this instance can only be set once.
RTPRECONDITION( !hasSession() );
_session = s;
};

RTRBOOL Request::hasSession()
{
return _session != 0 ? RTRTRUE : RTRFALSE;

SFC Developer’s Guide 215


4.7 SFC MODELS

};

void Request::start()
{
RTPRECONDITION( hasSession() );
sendRequest();
};

void Request::sendRequest()
{
RTPRECONDITION( _session != 0 );

cout<<"Requestor: Sending request message "<<_messageCount;


cout<<" to Reply peer instance "<<_session->name()<<endl<<endl;

// Allocate a message from the message session


_session->allocateMessage();

// Check if message is allocated.


if (_session->isMessageAllocated())
{
// Obtain an iterator to the allocated message
RTRMessageWriteIterator msg = _session->lastAllocatedMessage();

// Format the length of the string part


msg.appendUnsigned32(_requestString.count());

// Format the string part.


msg.appendString(_requestString);

// Format the message number


msg.appendUnsigned16(_messageCount++);

// Send the message to the peer.


msg.send();

// Check that session is still connected after the


// message write. If not, then this session is
// permanently disconnected, so process like a
// disconnect.

SFC Developer’s Guide 216


4.7 SFC MODELS

if (!_session->connected())
processSessionDisconnected(*_session);
}
else
// The processSessionAllocationReady() method will be
// invoked by the message session when more messages
// can be sent.
cout<<"Requestor: Unable to send message! Waiting..."<<endl;
};

void Request::activateTimer()
{
// Set the time, in seconds, for the timer and activate.
setTimerOffset((long)5, (short)0);
activate();
};

void Request::releaseResources()
{
// Delete the session.
if (_session != 0)
{
_session->terminate();
_session = 0;
}

// If timer is active, deactivate it.


if (active())
deactivate();
};

RTRString Request::_requestString = RTRString("HELLO. ARE YOUR THERE?");

4.7.4 TCP/IP Socket Implementation of Message Session

4.7.4.1 The Model


The RTRMessageSession class is an abstract class that defines methods for sending and receiving
messages with a peer session. Decisions regarding any communication protocols and mechanisms

SFC Developer’s Guide 217


4.7 SFC MODELS

that may be used to implement the abstract interface are determined by RTRMessageSession
descendants.
One such descendant relies upon the TCP/IP protocol suite and sockets to implement a message
session. TCP presents users with a client/server model in which a server is established on a well
known port and clients connect to that port to start a communication session. When the TCP server
receives a connection attempt, a new socket is allocated for communications with the TCP client.
The TCP implementation of the message session classes use a similar model. A TCP session server,
(RTRTcpSessionServer) is a TCP server that accepts connections from TCP client session instances
and propagates to its event client an event indicating that a new message session is available.
A TCP client session (RTRTcpClientSession) is a message session descendant that attempts to
establish a connection with a specific TCP session server instance. If the connection to the server
succeeds, the message session is considered established and messages may be passed between
itself and a peer session.
A TCP server session (RTRTcpServerSession) is a message session descendant that is created by
the TCP session server whenever another session connects to the session server. Upon creation, the
session is used to exchange messages with a peer TCP client session.

4.7.4.2 TCP Session Server Event Client Types


A TCP session server propagates events to a particular type of event client called a TCP session
server client (RTRTcpSessionServerClient). User defined classes inherit from a TCP session server
client and define appropriate actions to take when an event occurs. When a descendant of a TCP
session server client is notified of the availability of a new message session, it has the option to accept
or reject the new message session. A new message session is accepted by obtaining from the TCP
session server a TCP server session instance that will communicate with the peer TCP client session.
A new message session is rejected by simply ignoring the event notification. In this case the TCP
client session making the connection attempt will be left in a disconnected state.
The following section provides an example of a TCP session server client. Sample applications that
use this example and the Request and Reply classes defined in section 4.7.1 are provided after the
next section.

SFC Developer’s Guide 218


4.7 SFC MODELS

4.7.5 Example — A Simple TCP Session Server Client


This section provides an example that illustrates the behavior of a typical TCP session server client.
Note that this example makes use of the Reply class defined in section 4.7.2. The hypothetical
functional requirements for this client are as follows:
• An instance of this class monitors a single TCP session server, waiting for new sessions to
become available.
• An instance of this class always accepts a new message session when one becomes available.
• Whenever a new message session becomes available, an instance of this class creates a Reply
instance and provides it the message session.
• Reply instances will wait for messages from the peer Request instance and respond to the
messages received. The Request instance terminates communications after the tenth message is
returned by the peer Request instance.
To implement these requirements, this class must be designed so that:
• It creates a TCP session server instance.
• It is a TCP session server client and becomes the client for the TCP session server it creates.
• It exists in an error state if the TCP session server instance is in error.
For the purposes of this example, the TCP session server client implementation assumes that each
new message session is meant for a Reply instance and that each Reply instance will terminate itself.
The example header file which follows declares a descendant of RTRTcpSessionServerClient called
ReplyServer. RTRSessionServerClient declares one pure virtual method which must be implemented
by descendants. The ReplyServer class declares an implementation of this method, which is:
processNewSession(). This method passes two parameters: the TCP session server that propagated
the event and an identifier used to obtain the new message session from the TCP session server.
The implementation for this class follows the declaration. It illustrates the correct procedure for
obtaining a new message session from a RTRTcpSessionServer instance. Note that a new message
session may only be obtained while the thread of control is in the processNewSession() method.

4.7.5.1 Declaration for Reply Server (replysvr.h)


#ifndef _reply_server_h
#define _reply_server_h

SFC Developer’s Guide 219


4.7 SFC MODELS

#include "rtr/rtrdefs.h"
#include "rtr/rtstring.h"// String
#include "rtr/msgsess.h"// Message session
#include "rtr/tcpssvr.h"// Tcp Session Server

class ReplyServer
: public virtual RTRTcpSessionServerClient
// Inherit TCP session server client to receive event notification.
{
public:
// Constructor
ReplyServer(RTRTcpSocketIdentifier& identifier);

// Destructor
~ReplyServer();

// From RTRMessageSessionServerClient
void processNewSession(RTRTcpSessionIdentifier& id,
RTRTcpSessionServer& svr);
// This method is invoked when a new message session is
// available from the session server.

// Locally introduced method(s)


RTRBOOL error();
// Is the server in an error state? True if unable
// to create session server.

const char *errorText();


// Text describing the error.

protected:
RTRTcpSessionServer _server;
// Session server instance
};

#endif // _reply_server_h

SFC Developer’s Guide 220


4.7 SFC MODELS

4.7.5.2 Definition for Reply Server (replysvr.C)


#include "rtr/selectni.h"
#include "rtr/tcpidimp.h"// Tcp socket identifier
#include "replysvr.h"// Reply server
#include "reply.h"// Reply

ReplyServer::ReplyServer(RTRTcpSocketIdentifier& identifier)
: _server(identifier.to_c(),
identifier,
*this)
{
// The Tcp Session Server is created with this instance as
// the event client. Note that default values will be used
// for configurable variables of the message session instances
// created by this session server.
};

ReplyServer::~ReplyServer()
{
};

void ReplyServer::processNewSession(RTRTcpSessionIdentifier& id,


RTRTcpSessionServer& svr)
{
Reply *_newReply = new Reply;
// Create new Reply instance for the peer Request
// instance.

RTRString sessionName("ReplySession");

RTRTcpServerSession::setDefaultNumberWriteMessages(5);
RTRTcpServerSession::setDefaultWriteMessageSize(200);

// Create a message session for use by Reply instance


// to communicate with peer.
RTRMessageSession* _session = svr.createSession( id,
*_newReply);

// Give new message session to the Reply instance.

SFC Developer’s Guide 221


4.7 SFC MODELS

_newReply->setSession(_session);

cout<<"ReplyServer: New Requestor added to communicate with Request


instance at "<<_session->name()<<endl;

};

RTRBOOL ReplyServer::error()
{
// Reply server’s error is based on state of it’s
// TCP session server.
return _server.error();
};

const char* ReplyServer::errorText()


{
// Reply server’s error text based on TCP session
// server’s error text.
return _server.errorText();
};

4.7.6 Example — A Simple Application Using ReplyServer


This section provides the text of an application that uses the ReplyServer class from section 4.7.5 and
the Reply class from section 4.7.2. This text is also found in the file replysvr.C.
main(int argc, char **argv)
{
if (argc == 2)
{
// Create a tcp socket identifier that identifies the
// port number this Tcp Session Server will establish
// itself on.
RTRTcpSocketIdentifierImpl _serverSocketId(argv[1]);
if (_serverSocketId.isValid())
{
// Create the client for the Tcp Session Server
ReplyServer _replyServer(_serverSocketId);

// Check that ReplyServer instance started


// properly.

SFC Developer’s Guide 222


4.7 SFC MODELS

if (!_replyServer.error())
{
cout<<endl<<"Reply server ready for requests"<<endl;

// Enable the "main loop"


RTRSelectNotifier::run();
return 0;
}
else
cout<<"ReplyServer error: "<<_replyServer.errorText()<<endl;
}
else
{
cout<<"TcpSocketIdentifier error: ";
cout<<_serverSocketId.errorText()<<endl;
}
}
else
cout<<"Usage: "<<argv[0]<<" service_name"<<endl;

return -1;
}

4.7.7 Example — A Simple Application Using a TCP Client Session


This section provides the text of an application that uses the RTRTcpClientSession class and the
Request class from section 4.7.3. This text is also found in the file request.C.
// The main text of an application that uses a Request class. This
// program instantiates an instance of RTRTcpClientSession using the
// host name and server name provided on the program command line.
main(int argc, char **argv)
{
if (argc == 3)
{
RTRString _sessionName("tcpClientSession"); // Name of the session.
RTRString _hostName(argv[1]);
RTRString _serviceName(argv[2]);

// Create a tcp socket identifier that identifies the


// host id and port number of the peer session that

SFC Developer’s Guide 223


4.7 SFC MODELS

// this Tcp Client Session will communicate with.


RTRTcpSocketIdentifierImpl _socketId(_hostName, _serviceName);

if (_socketId.isValid())
{
// Create the client of the Tcp Client Session.
Request *_requestor = new Request();

RTRTcpClientSession *_session;

RTRTcpClientSession::setDefaultWriteMessageSize(300);
RTRTcpClientSession::setDefaultNumberWriteMessages(2);
RTRTcpClientSession::setDefaultReadBias(3);

// Create a Tcp Client Session that will attempt to establish


// communications with a peer Tcp Server Session specified by
// _socketId. The client for this message session, _requestor,
// will be notified whenever a message is received from its
// peer and whenever the state of the session changes.
_session = new RTRTcpClientSession( _socketId,
*_requestor);
if (_session->connected())
{
cout<<"Client: Activating requestor..."<<endl;

// This client will also send messages and therefore


// needs access to the message session.
_requestor->setSession(_session);

// Start sending request messages.


_requestor->start();

// Enable the "main loop"


RTRSelectNotifier::run();;
return 0;
}
else
{
cout<<"Session error: "<<_session->text()<<endl;

SFC Developer’s Guide 224


4.7 SFC MODELS

// Clean up
delete _session;
_session = 0;
}
}
else
{
cout<<"Socket identifier invalid : "<<_socketId.errorText()<<endl;
}
}
else
cout<<"Usage: "<<argv[0]<<" host_name service_name"<<endl;

return -1;
}

SFC Developer’s Guide 225


4.8 SFC MODELS

4.8 Support
This cluster describes the SFC "infrastructure" models:
• connection classes (section 4.8.1)
• service pool factory classes (section 4.8.2)
• the event loop abstraction and implementation (section 4.8.3)
• configuration classes (section 4.8.5)
• event logging classes (section 4.8.6)
• command line classes (section 4.8.7)
• international character support (section 4.8.8.7)

4.8.1 Connection

4.8.1.1 Overview
The connection classes provide a way to control and monitor the connection between SFC and a
market data infrastructure. The abstract base class for connections is RTRMDConnection. Market data
connections are created internally by most market data services and by service pool factories (section
4.8.2), so SFC applications typically do not have to use them directly. Connection classes can be
useful in the following circumstances.
• The application needs to monitor the status of the connection. A class which inherits from
RTRMDConnectionClient can register to receive status and information events from a connection.
• Multiple services need to share a connection. The connection can be created and passed into the
constructors of the services. Most of the time, it’s easier to use a service pool factory. However,
this approach is especially useful for sharing a RTRTIBConnection between consuming and
publishing services, since publishing services are not maintained by service pool factories.
• The application needs fine-tuned control over connection parameters. Some parameters can be
controlled through parameters on services or service pool factories. Most parameters can also be
controlled through configuration. The connection classes can be used to directly set the mount
parameters without using a configuration file. All mount parameters must be set before calling
connect() which puts the connection in an initalized state.

SFC Developer’s Guide 226


4.8 SFC MODELS

4.8.1.2 Implementation
SFC includes three implementations of RTRMDConnection: RTRSSLConnection,
RTRSSLConnectionServer, and RTRTIBConnection. Each implementation class has unique mount
parameters and connection values that are type specific. See the SFC Reference Manual for details on
these parameters.
When entitlements are enabled, RTRTIBConnection represents both the RVD connection and the
connection to the DACS daemon. An entitled TIB connection is only connected when both connections
have been established. RTRTIBConnection can connect to a Rendezvous network using either the
SASS2 protocol or the SASS3 protocol. By default, it uses RTRTIBConnection::SASS3. It can be
changed on a per connection basis using:
RTRTIBConnection::protocol(RTRTIBConnection::Protocol p)

When entitlements are disabled, a RTRSSLConnectionServer is connected as long as the well-known


listen port could be opened. Note that no other application needs to actually be "connected."
When entitlements are enabled, RTRSSLConnectionServer is only connected when both the well-
known port is open and the connection to the DACS daemon has been established. If the user login to
the DACS daemon fails, the well-known port will be closed.
For information on the specific mount parameters for each implementation, see the SFC Reference
Manual and section 5.5.10 in this manual.

4.8.1.3 Examples
The following code shows how to create a TIB connection. Most of the connection parameters can be
set in the constructor.
RTRObjectId _instanceId("appId");
RTRTIBConnection _connection(_instanceId, "TIBConnection",
service, network, daemon);
_connection.connect();
Additional connection parameters are needed when using a TMF in an RMDS infrastructure (Appendix E).
This second example shows how to create a TIB connection with a TMF session. All of the TMF
session parameters can be set through the setUpdateSession() method.
RTRObjectId _instanceId("appId");
RTRTIBConnection _connection(_instanceId, "TIBConnection",

SFC Developer’s Guide 227


4.8 SFC MODELS

service, network, daemon);


_connection.setUpdateSession(updateService, updateNetwork, updateDaemon);
_connection.connect();

This third example shows how to create an SSL connection. Since SSL has more connection
parameters, they cannot be set on the constructor. Instead, they are set individually before calling
connect().
RTRObjectId _instanceId("appId");
RTRSSLConnection _connection(_instanceId, "sslDispatcher");
_connection.userName("jsmith");
_connection.serverList("sinkdistmach1 sinkdistmach2");
_connection.port(8102);

// all mount parameters must be set before calling connect


_connection.connect();

4.8.2 Service Pool Factory

4.8.2.1 Overview
Service pool factories make it easier to create and manage the life-cycle of market data connections,
FID databases, services, and service pools. A service pool factory is responsible for creating and
destroying its connection, services, and pools. The abstract base class for service pool factories is
RTRMDServicePoolFactory.
The RTRMDServicePoolFactory is responsible for specifying the service pool factory interface and
generic configuration. From this service pool factory, a program can retrieve RTRecord, Page,
RTPage, and TimeSeries service pools. The pools are created with lazy initialization. Since a factory
has a single connection, all of the pools uses that same, shared connection.The service pool factory
classes follow the Abstract Factory pattern [6] . RTRMDServicePoolFactory has two infrastructure-
specific subclasses: RTRSSLServicePoolFactory and RTRTIBServicePoolFactory.
The Composite pattern [6] is used by RTRCompositeServicePoolFactory to provide a way of merging
service pools from multiple factories into a set of pools. For example, this feature can be used to
automatically create a single RTRRTRecordServicePool that contains services from two SSL and one
TIB connection. If there is a service name conflict, services are included in the composite pool on a
first-come, first serve basis. Conflicts are also logged.

SFC Developer’s Guide 228


4.8 SFC MODELS

4.8.2.2 Implementation
While the abstract class for service pool factories has an infrastructure-agnostic interface, some
implementation details should be considered.
• On Triarch, services can be dynamically discovered. To disable this feature,
enableDynamic*ServicePool configuration variables were added to RTRMDServicePoolFactory
to turn this functionality on and off. By default these values are enabled by
RTRSSLServicePoolFactory. However with RTIC (SASS2), all services names must be known by
the application. So, these values are disabled and ignored by RTRTIBServicePoolFactory.
• Since services cannot be dynamically determined on RTIC (SASS2), they must be specified with
configuration or by calling one of the install*Service(const char*) methods. It may be useful to
note that theses services are generic, so they can be add services when dynamic services are
disabled on Triarch, or they can be used to ensure certain services are listed first in the pool.
• Page stream services are not available on RTIC (SASS2), so rtPageServicePool() returns 0. In
general, the return values of pageServicePool(), timeSeriesServicePool(), and
rtRecordServicePool() should always be checked if they are null before being used.
• RTRSSLServicePoolFactory and RTRTIBServicePoolFactory each have some additional
configuration variables that can be used to customize their connections.

4.8.2.3 Examples
The following example code shows how SSL and TIB service pool factories are created and how a
composite factory can be used:
RTRObjectId instanceId("appId");

RTRCompositeServicePoolFactory factory( instanceId, "compositePool");

RTRSSLServicePoolFactory sslFactory( instanceId, "pool");


factory.addFactory(sslFactory);

RTRTIBServicePoolFactory tibFactory( _instanceId, "pool");


factory.addFactory(tibFactory);

// At this point, all of the service pools don’t exist because they are
// created with lazy initialization.

SFC Developer’s Guide 229


4.8 SFC MODELS

tibFactory.installRTRecordService("RSF");
// A RTRTIBRTRecordService named RSF is created and added to the new
// RTRRTRecordServicePools in _tibFactory and _factory.

RTRRTRecordServicePool *pool = factory.rtRecordServicePool();


// The RTRRTRecordServicePool is created in the ssl factory.
// _pool already contains RSF. SSL services will be added when
// they are asynchronously discovered from Triarch.

More Examples
The connection and factory models and the single service constructors were designed for both
flexibility and ease of use. While on the surface, the wide variety of these examples may seem
complicated, they are shown here as a demonstration of SFC’s initantiation flexibiliy. Please keep in
mind, for most purposes, a factory or single service constructor will work with minimal setup.
These examples may use the following includes and declarations:
#include "rtr/objid.h" // RTRObjectId
#include "rtr/tibrtsvc.h"// RTRTIBRTRecordService
#include "rtr/sslrtrs.h" // RTRSSLRTRecordService
#include "rtr/tconnect.h"// RTRTIBConnection
#include "rtr/sconnect.h"// RTRSSLConnection
#include "rtr/sslconns.h"// RTRSSLConnectionServer
#include "rtr/tibsplf.h" // RTRTIBServicePoolFactory
#include "rtr/sslsplf.h" // RTRSSLServicePoolFactory
#include "rtr/fldtossl.h"// RTRRTFieldToSSLRecordService
#include "rtr/fldtotib.h"// RTRRTFieldToTIBRecordService
RTRObjectId appId("appId");
1. Single SASS3 service
RTRTIBRTRecordService service(appId, "RSF");
2. Single SASS3 service with mount parameters
RTRTIBRTRecordService service(appId, "RSF", "7501", "tcp:rvdhost:7500");
3. Single SASS2 service
RTRTIBConnection::DefaultSassVersion = RTRTIBConnection::SASS2;
RTRTIBRTRecordService service(appId, "RSF");
4. Single SASS2 service with mount parameters

SFC Developer’s Guide 230


4.8 SFC MODELS

RTRTIBConnection::DefaultSassVersion = RTRTIBConnection::SASS2;
RTRTIBRTRecordService service(appId, "RSF", "7501", "", "tcp:rvdhost:7500");
5. Single SSL service, using sslapi.cnf or ipcroute for mount location
RTRSSLRTRecordService service(appId, "IDN_SELECTFEED", "");
6. Single SSL service, customizing mount location
RTRSSLRTRecordService service(appId, "IDN_SELECTFEED", "sinkDistHost1
sinkDistHost2");
7. Customizing connection for single SASS3 service
RTRTIBConnection connection(appId, "tibconnection", "7501");
connection.userName("mylogin");
connection.connect();
RTRTIBRTRecordService service(appId, "RSF", connection);
8. Customizing connection for single SASS3, TMF service
RTRTIBConnection connection(appId, "tibconnection", "7501");
connection.setUpdateSession("7502", "", "");
connection.connect();
RTRTIBRTRecordService service(appId, "RSF", connection);
9. Customizing connection for single SASS2 service
RTRTIBConnection connection(appId, "tibconnection", "7501");
connection.enableEntitlements(RTRFALSE);
connection.protocol(RTRTIBConnection::SASS2);
connection.connect();
RTRTIBRTRecordService service(appId, "RSF", connection);
10.Customizing connection for single SSL service
RTRSSLConnection connection(appId, "sslconnection");
connection.userName("mylogin");
connection.protocol(RTRTIBConnection::SASS2);
connection.connect();
11. Two SASS3 services from factory
RTRTIBServicePoolFactory factory(appId, "factory");
// the next two lines are not needed if the config file includes
// *appId.factory : RSF, RDF

SFC Developer’s Guide 231


4.8 SFC MODELS

factory.installRTRecordService("RSF");
factory.installRTRecordService("RDF");
RTRRTRecordServicePool *pool = factory.rtRecordServicePool();
RTRRTRecordService *s1 = pool->service("RSF");
RTRRTRecordService *s2 = pool->service("RDF");
12.Two SASS2 services from factory
// The next two lines could be replaced with
// RTRTIBConnection::DefaultSassVersion = RTRTIBConnection::SASS2;
RTRTIBConnection connection(appId, "tibconnection", "7501");
connection.protocol(RTRTIBConnection::SASS2);
RTRTIBServicePoolFactory factory(appId, "factory", connection);
// the next two lines are not needed if the config file includes
// *appId.factory : RSF, IDN_RDF
factory.installRTRecordService("RSF");
factory.installRTRecordService("IDN_RDF");
RTRRTRecordServicePool *pool = factory.rtRecordServicePool();
RTRRTRecordService *s1 = pool->service("RSF");
RTRRTRecordService *s2 = pool->service("IDN_RDF");
13.Two SSL services from factory
RTRSSLServicePoolFactory factory(appId, "factory");
// the next two lines are not needed if the config file includes
// *appId.factory : IDN_SELECTFEED, IDN_RDF
factory.installRTRecordService("RSF");
factory.installRTRecordService("IDN_RDF");
RTRRTRecordServicePool *pool = factory.rtRecordServicePool();
RTRRTRecordService *s1 = pool->service("IDN_SELECTFEED");
RTRRTRecordService *s2 = pool->service("IDN_RDF");
OR
// AppRecSrvcPoolClient client, subclass of RTRRTRecordServicePoolClient
RTRSSLServicePoolFactory factory(appId, "factory");
RTRRTRecordServicePool *pool = factory.rtRecordServicePool();
pool->addClient(client);

// Release control to SFC’s event loop. Wait for service table


// to be downloaded asynchronously from sink distributor.
void AppRecSrvcPoolClient::processRTRecordServiceAdd(
RTRRTRecordServicePool & pool, RTRRTRecordService & srvc)

SFC Developer’s Guide 232


4.8 SFC MODELS

{
if (srvc.name() == "IDN_SELECTFEED")
s1 = &srvc;
else if (srvc.name() == "IDN_RDF");
s2 = &srvc;
}
14.Two SASS3 services with two connections
RTRTIBRTRecordService s1(appId, "RSF");
RTRTIBRTRecordService s2(appId, "RDF");
15.Two SASS2 services with separate connections
RTRTIBConnection::DefaultSassVersion = RTRTIBConnection::SASS2;
RTRTIBRTRecordService s1(appId, "RSF");
RTRTIBRTRecordService s2(appId, "RDF");
16.Two SSL services with two connections
RTRSSLRTRecordService s1(appId, "IDN_SELECTFEED", "");
RTRSSLRTRecordService s2(appId, "IDN_RDF", "");
17.Two SASS3 service with one connection
RTRTIBRTRecordService s1(appId, "RSF");
RTRTIBConnection &connection = s1.connection();
RTRTIBRTRecordService s2(appId, "RDF", connection);
18.Two SASS2 service with one connection
RTRTIBConnection::DefaultSassVersion = RTRTIBConnection::SASS2;
RTRTIBRTRecordService s1(appId, "RSF");
RTRTIBConnection &connection = s1.connection();
RTRTIBRTRecordService s2(appId, "RDF", connection);
19.Two SSL services with one connection
RTRSSLRTRecordService s1(appId, "IDN_SELECTFEED", "");
RTRSSLConnection &connection = s1.connection();
RTRSSLRTRecordService service(appId, "IDN_RDF", connection);
20.Single SSL pub service
RTRRTFieldToSSLRecordService s1(appId, "MY_SRVC1")

SFC Developer’s Guide 233


4.8 SFC MODELS

21.Two SSL pub services with separate connections


// triarch_sink and triarch_sink2 must be configured to be different
// ports, or else the second connection server will not be able to
// open the port to listen for incoming connections.
RTRSSLConnectionServer sslconnsvr1(appId, "connection1", "triarch_sink");
RTRRTFieldToSSLRecordService s1(appId, "MY_SRVC1", sslconnsvr1);
RTRSSLConnectionServer sslconnsvr2(appId, "connection2", "triarch_sink2");
RTRRTFieldToSSLRecordService s2(appId, "MY_SRVC2", sslconnsvr2);
22.Two SSL pub services with one connection
RTRRTFieldToSSLRecordService s1(appId, "MY_SRVC1");
RTRSSLConnectionServer & connectionServer = s1.connectionServer();
RTRRTFieldToSSLRecordService s2(appId, "MY_SRVC2", connectionServer);
RTRRTFieldToTIBRecordService pubsrvc(appId, "MY_SRVC", connection);
23.SASS3 sub and pub services with same connection
RTRTIBRTRecordService subsrvc(appId, "RSF");
RTRTIBConnection & connection = subsrvc.connection();
RTRRTFieldToTIBRecordService pubsrvc(appId, "MY_SRVC", connection);
24.SASS2 sub and pub services with same connection
RTRTIBConnection::DefaultSassVersion = RTRTIBConnection::SASS2;
RTRTIBRTRecordService subsrvc(appId, "RSF");
RTRTIBConnection & connection = subsrvc.connection();
25.Changing connection parameters for a service pool factory
RTRSSLConnection connection(appId, "connection");
connection.userName("myusername");
connnection.connect();
RTRSSLServicePoolFactory factory (appId, "pool", connection);
26.Multiple infrastructure services from single pool
RTRCompositeServicePoolFactory factory( appId, "compositePool");
RTRSSLServicePoolFactory sslFactory( appId, "pool");
factory.addFactory(sslFactory);
RTRTIBServicePoolFactory tibFactory( appId, "pool");
factory.addFactory(tibFactory);
tibFactory.installRTRecordService("RSF");
RTRRTRecordServicePool *pool = factory.rtRecordServicePool();

SFC Developer’s Guide 234


4.8 SFC MODELS

4.8.3 Event Loop


This model defines the abstract and implementation classes for an event dispatching loop. The SFC
abstraction for an event loop is represented by the class RTREventNotifier. The purpose of the notifier
is to allow application components to use system resources (I/O, timers) in a cooperative way, without
being dependent on any particular implementation of a "main loop". Application designers may choose
the event loop implementation which best suits their requirements.
There can be only one event loop (RTREventNotifier) in an application. SFC classes access the
notifier implementation via a static data element of type RTREventNotifierInit. This static data element
is made available to an application component by including the file rtr/rtrnotif.h. The actual
implementation used depends on how the application is constructed (what main() looks like) and how
the application is linked. Usually, the main() is "notifier specific". This is because, in most applications,
main() must invoke the instructions which cause the application to enter the loop and such instructions
couple the main with a particular implementation of notifier. For example, the applications described in
this manual use the RTRSelectNotifier. Example source files that define main() include the header file
rtr/selectni.h and invoke RTRSelectNotifier::run() to enable the control loop.
In a Windows NT environment, several options are available for the event loop:
• Use the RTRSelectNotifier, as described above. However, due to a bug in the operating system,
NT’s select() call can only poll 64 file descriptors. This limit applies to incoming and outgoing
socket descriptors.
• In a GUI application, use the RTRWindowsNotifier. To use this notifier, simply link libwinml.lib
into the executable, or compile the winni.cpp provided into the program. The
RTRWindowsNotifier will use Windows’ event dispatching loop automatically, so run() does not
need to be called.
• Use the RTRWindowsNotifier explicitly in a console application. Since a window dispatching loop
does not exist in a console application, the application must have its own dispatch loop:
#include <windows.h>
int main()
{
// ...application setup
MSG msg;
void *notif = RTREventNotifierInit::notifier;
static RTRWindowsNotifier * wnotif =
((RTRWindowsNotifier*)notif->instance()

SFC Developer’s Guide 235


4.8 SFC MODELS

while (GetMessage(&msg, 0, 0, 0) && wnotif->enabled() )


DispatchMessage(&msg);

// ...cleanup
}

• The RTRWindowsNotifier can be used when MFC is used. If MFC is used and the event loop is to
be compiled into a DLL, use libmfcml.lib.

4.8.3.1 I/O Events


The base class for components which need to be informed of I/O events is RTRIOClient. This class
provides event handling methods for each of three types of I/O event available on file descriptors.
• A Read event indicates to interested clients that there is data to be read on a given file descriptor.
• A Write event indicates that a given file descriptor is now available for output.
• An Exception event indicates that there is an exception condition on a given file descriptor.
Descendants of RTRIOClient may register for each type of I/O event with an instance
RTREventNotifier. Only one client may register for a particular event on any one file descriptor.
Since RTRIOClient does not detect the loss of I/O events, the application should handle it in the
application level. For example, if the application implements RTRIOClient for a READ event on a given
file descriptor, the application should check its status continuously and call the method below in
processIORead() if the I/O event is closed or lost.
RTREventNotifierInit::notifier->dropReadClient(fd)
This will protect the application from sending processIORead events in an infinite loop.

4.8.3.2 Timer Events


Timer events allow application components to give up control of the thread of execution in the program
until a specified amount of time has elapsed. RTRTimerCmd is the base class that allows application
components to initiate and receive timer events. This base class provides methods used to set the
timer interval (offset) and activate or deactivate the timer. Descendants of RTRTimerCmd provide an
implementation of the processTimerEvent() method. This method is called when the timer expires.

SFC Developer’s Guide 236


4.8 SFC MODELS

Timers have minimal resolutions set by the operating systems. The default minimal resolution is set at
10ms. Some operating systems round off timers, so setting a timer for 23 ms may actually set a timer
of 30ms.
Applications can set a repeating timer by calling activate() inside processTimerEvent(). This sets a
timer event to execute in a user determined amount of time in the future. If the timer set in the
processTimerEvent() is a null timer, this timer will be automatically set to the minimal resolution time
(10ms). This is also true for timers set inside of a windows event callback.

NOTE: For performance reasons, the SFC notifier implementations only check the current time
once through a notifier loop. This means that timers set at the beginning and end of a callback will
be set to fire at the same system time.

4.8.3.3 Custom Event Loop


One may implement a custom event loop to use in place of SFC’s event loop; however, this
implementation of event loop must consider all of these issues:
• Timers can be set from many parts of SFC, including, but not limited to, request retry and timeout,
reconnection delays, cleanup.
• Null timers must be handled correctly and effeciently. Null timers are often introduced during
cleanup to let the call stack safely unwind before calling the destructor. Not handling null timers
efficiently could result in extremely slow recovery.
• Multiple callbacks from application to the notifier must be handled correctly.
• Callbacks within callbacks must be handled correctly
• I/O and Timer events must be handled correctly.
See section 4.8.4 for more information on timers.

4.8.4 Example — I/O and Timing


This section presents an example class that utilizes both the I/O and timing events. IOTimerClient is a
descendant of both RTRIOClient and RTRTimerCmd. The purpose of this class is to read data from
the standard input device. That data is interpreted as an interval, in seconds, which is used as the
interval to be timed. When new data is received, the current timer event, if any, is canceled and the
timer event is re-activated with the new interval. If the timer expires, a message is printed to the
standard output device.

SFC Developer’s Guide 237


4.8 SFC MODELS

Each of the examples which follows uses a different version of the notifier and instantiates one
instance of IOTimerClient.

4.8.4.1 Declaration of IOTimerClient (iotimerclient.h)


//
// This file contains the declaration for IOTimerClient, a simple class
// which uses both I/O and timing events. It reads the standard input for
// line of data. The data is converted to an integer value and is used to
// set a timer. When the timer expires, the message "HELLO WORLD, AGAIN" is
// printed to the standard output. Existing timers are canceled prior to
// installation of new timers. A timer value of 0 causes this class to
// stop waiting for input.
//

#include "rtr/timercmd.h"
#include "rtr/ioclient.h"

class IOTimerClient :
public RTRTimerCmd,
public RTRIOClient
{
public:
// Constructor
IOTimerClient(char *);

// Destructor
~IOTimerClient();

// Event processing - from RTRIOClient


void processIORead(int fd);

// Event processing - from RTRTimerCmd


void processTimerEvent();

protected:
// Implementation attributes
int fd;
};

SFC Developer’s Guide 238


4.8 SFC MODELS

4.8.4.2 Definition of IOTimerClient (iotimerclient.C)


//
// This file contains the implementation of IOTimerClient
//

#ifndefIBMRS
#include <sys/unistd.h>
#endif
#include <unistd.h>
#include <fcntl.h>
#include <iostream.h>
#include <stdlib.h>

#include "rtr/rtrnotif.h"
#include "iotimerclient.h"

IOTimerClient::IOTimerClient(char *fnm)
{
fd = open(fnm, O_RDWR);
RTREventNotifierInit::notifier->addReadClient(*this, fd);
cout << "Enter time:" << flush;
}

IOTimerClient::~IOTimerClient()
{
RTREventNotifierInit::notifier->dropReadClient(fd);
}

void IOTimerClient::processIORead(int)
{
char buf[100];
int len = read(fd, buf, 10);
buf[len] = ‘\0’;

int s = atoi(buf);
if (active())
{
cout << "Canceling current event" << endl;
deactivate();

SFC Developer’s Guide 239


4.8 SFC MODELS

}
if ( s > 0 )
{
cout << "Adding event for " << s << " seconds" << endl;
setTimerOffset(s, 0);
activate();
}
else
{
if ( active() )
deactivate();
RTREventNotifierInit::notifier->dropReadClient(fd);
}
}

void IOTimerClient::processTimerEvent()
{
cout << "HELLO WORLD, AGAIN" << endl << "Enter time:" << flush;
}

4.8.4.3 Example Application - Select based (selecttest.C)


//
// This application creates a single instance of a IOTimerClient.
// It uses the RTRSelectNotifier as the main loop implementation.
//

#include "rtr/selectni.h"// Defines RTRSelectNotifier

#include "iotimerclient.h"

void main()
{
IOTimerClient client("/dev/tty");
RTRSelectNotifier::run();
}

SFC Developer’s Guide 240


4.8 SFC MODELS

4.8.4.4 Example Application - Xt based (xttest.C)


RTRXtNotifier has a static data member of type XtAppContext called appContext. This must be
declared and initialized by the application. The main loop is started in the usual manner by calling
XtAppMainLoop().
//
// This application demonstrates the use of the RTRXtNotifier. It
// creates a single instance of a IOTimerClient and creates a simple
// X application.
//

#include <stdio.h>

#include "rtr/xtenimp.h"
#include "iotimerclient.h"

#define XTFUNCPROTO 1

#include <X11/Intrinsic.h> /* Intrinsics Definitions */


#include <X11/IntrinsicP.h> /* Intrinsics Definitions */
#include <X11/StringDefs.h> /* Standard Name-String definitions */
#include <X11/Xaw/Command.h> /* Athena Command Widget */

#define MAXLEN 50

static void IncrementCount(Widget w, XtPointer clientData, XtPointer CallData)


{
char string[MAXLEN];
static int count;
Arg args[3];
int i;

sprintf(string, "click me: %d", ++count);

i = 0;
XtSetArg(args[i], XtNlabel, string); i++;
XtSetValues(w, args, i);
}

XtAppContext RTRXtNotifier::appContext = 0;

SFC Developer’s Guide 241


4.8 SFC MODELS

int main(int argc, char **argv)


{
XtAppContext app_context;
Widget topLevel, hello;
Arg arg;
char *p;

topLevel = XtAppInitialize(
&app_context,
"XClickcount", /* Application class */
NULL, /* Resource Mgr. options */
0, /* number of RM options */
#if (XtSpecificationRelease < 5)
(Cardinal *)&argc, /* number of args */
#else
&argc, /* number of args */
#endif
argv, /* command line */
NULL,
&arg,
0
);

hello = XtCreateManagedWidget(
"click me", /* arbitrary widget name */
commandWidgetClass, /* widget class from Label.h */
topLevel, /* parent widget*/
NULL, /* argument list */
0 /* arg list size */
);

XtAddCallback( hello, XtNcallback,


(XtCallbackProc) IncrementCount,
(XtPointer) NULL );

XtRealizeWidget(topLevel);
XtResizeWidget(topLevel, 120, 80, 10);

RTRXtNotifier::appContext = app_context;

SFC Developer’s Guide 242


4.8 SFC MODELS

IOTimerClient client("/dev/tty");

XtAppMainLoop(app_context);
}

4.8.4.5 Example Application - XView based (xvtest.C)


RTRXViewNotifier has a static data member of type Frame called baseFrame. This must be declared
and initialized by the application. The main loop is started in the usual manner by calling
xv_main_loop().
#include "rtr/xvenimp.h"

#include "iotimerclient.h"

#define __sys_unistd_h
#define __SIGNAL_H

extern "C" {
#include <xview/xview.h>
#include <xview/panel.h>
#include <xview/openmenu.h>
}

int
selected(Panel_item item, Event *)
{
printf("%s selected\n", xv_get(item, PANEL_LABEL_STRING));
return XV_OK;
}

void
menu_proc(Menu, Menu_item)
{
}

Frame RTRXViewNotifier::baseFrame = 0;

int main(int argc, char **argv)


{

SFC Developer’s Guide 243


4.8 SFC MODELS

Panel panel;
Menu menu;
Frame base_frame;

xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);


base_frame = (Frame)xv_create(NULL, FRAME, NULL);
panel = (Panel)xv_create(base_frame, PANEL, NULL);

menu = (Menu) xv_create(NULL, MENU,


MENU_NOTIFY_PROC, menu_proc,
MENU_STRING, "YES", "No", "Quit", NULL,
NULL);
(void) xv_create(panel, PANEL_BUTTON,
PANEL_LABEL_STRING, "Click me",
PANEL_NOTIFY_PROC, selected,
PANEL_ITEM_MENU, menu,
NULL);
window_fit(panel);
window_fit(base_frame);

RTRXViewNotifier::baseFrame = base_frame;
IOTimerClient client("/dev/tty");

xv_main_loop(base_frame);
}

4.8.5 Configuration

4.8.5.1 Overview
In general, configuring software components is a matter of assigning values to named variables.
Reusable software, and in particular, object-oriented software, makes the problem more complicated.
The primary concern is avoiding name conflicts. Variable names must be chosen without knowledge of
the entire application. Another aspect of the problem is the complex composition of the end product,
and the fact that the same component may appear in many different applications. The SFC provides a
model to address these problems.
The SFC configuration model is derived from the following analysis:

SFC Developer’s Guide 244


4.8 SFC MODELS

• An application consists of a number of components.


• Each component is an instance of some type or class.
• The class of a component determines the set of variables whose values may be configured.
• Each variable has a name.
The model provides the means to assign values to variables by class identity and by instance identity.
Configuration by instance identity requires that the run-time composition of the application be known.
Configuration by class identity is more generalized and therefore easier, but does not provide as much
control; it is not as precise.
The class RTRConfigDb is the abstract base class for a database of configuration variables. Variables
are retrieved from the database on the basis of three pieces of information: a class identifier, an
instance identifier, and a variable name. Both identifiers are of type RTRObjectId, which essentially is
an encapsulation of a compound string. Configuration variables are of type RTRConfigVariable, which
provides convenient mechanisms for interpreting the value in different ways. RTRConfigDb allows the
requesting component to specify a default value which will be used when no explicitly configured value
is available. The use of default values is optional. It is a design issue. Variables for which there is no
value and no default will be in an error state.
Class identifiers are assigned to components by the class designer. They are compiled into the
software. All instances of a particular type (class) will have the same class identifier. Instance
identifiers are generated at run-time. The manner in which instance identifiers are assigned is an
application design issue. No two components should have the same instance identifier. The next two
sections provide some guidelines on how to go about assigning class and instance identifiers.

4.8.5.2 Assigning Class Identifiers


Class identifiers are arbitrary values which should usually correspond fairly closely to the C++ class
types of the component in question. Why reinvent the wheel? Most of the time, this is a fairly
straightforward problem. Difficulties arise when using inheritance, especially when the class in
question has multiple ancestors which need access to configuration data. A certain amount of foresight
is required by the base class designers.
A simple example:
The TickerMonitor class from the ticker example program has a static data member of type
RTRObjectId. It is called _classId and is used as a class identifier in configuration queries. The
value assigned to it (in tickmon.C) is "TickerMonitor". This technique works well enough for this

SFC Developer’s Guide 245


4.8 SFC MODELS

class, but is not very extensible. Suppose TickerMonitor had a descendant called Foo, also
needing configuration. The class identifier should be "TIckerMonitor.Foo". Foo can declare its
own instance of RTRObjectId and initialize it appropriately. The problem is that when the method
Foo::processRTRecordServiceAdd is invoked, it will use the class identifier from the ancestor
(TickerMonitor) not the identifier of the descendant (TickerMonitor.Foo).
Solving this problem requires a change in design of the TickerMonitor class. The class identifier should
not be hard-coded. One solution is to provide a constructor argument which has a default value and
use that to initialize a class identifier object. The new constructor for TickerMonitor would be declared
as follows:
TickerMonitor(
const RTRObjectId&,
const char *,
RTRRTRecordServicePool&,
const char* classId = "TickerMonitor");
....
protected:
RTRObjectId _classId;
Then the initialization list needs an entry:
_classId(classId)
The descendant class Foo then invokes the constructor with the fourth argument set to
"TickerMonitor.Foo".

4.8.5.3 Assigning Instance Identifiers


The purpose of an instance identifier is to uniquely identify a component. Why not use the address in
memory of that component, or perhaps use a counter to generate numeric identifiers? The problem
with these techniques is that they do not yield intuitive results and they are not predictable, making
these techniques impractical from an administrator’s perspective.
A reasonable solution is to create an identifier in the application which is the basis for all the other
identifiers. Each component of the application is given that identifier and a unique, meaningful name.
The application’s identifier is the context in which that name is unique. Each component can then pass
its own identifier into sub-components and assign them unique names, and so-on and so-on. This
process is more predictable and yields unique, meaningful names.

SFC Developer’s Guide 246


4.8 SFC MODELS

The examples in this manual use this technique. For example, the ticker application (ticker.C) which
creates an instance of TickerMonitor has an application identifier of "ticker". This is passed to the
instance of TickerMonitor along with a unique name, in this case "ticker_monitor". The service pool in
this application can also be configured; its unique name is "pool". This means that the instance of
TickerMonitor has an instance identifier of "ticker.ticker_monitor", and the pool has an instance
identifier of "ticker.pool".
This technique works well in most cases but has some flaws. If two of these applications run on the
same system and use the same configuration file, there is no way to tell them apart. The application
designer may want to ensure uniqueness by providing a command line argument which gives this
application its name. Further more, in distributed systems, it may be appropriate to use the hostname
as the first level of identification.

4.8.5.4 An Implementation Using X-Window Resource Files


The SFC provides a file-based implementation of RTRConfigDb called RTRXFileDb which parses files
that use the same syntax as X-Window resource specification files. This syntax allows the
administrator to use wildcards in the specification of class and instance identifiers, making the
configuration task simpler.

4.8.5.5 RTRXFileDb Example


This sample program shows some simple uses for the configuration database. This example uses the
"X" file implementation of the configuration database which uses X library functions to read in
configuration variables from a disk file. These examples use meaningless identifiers and pass literal
strings instead of creating instances of RTRObjectId. The use of strings is acceptable because
RTRObjectId provides a constructor which accepts a string.
This small program creates an instance of RTRXFileDb, giving it the path of a configuration file
./config_file. Configuration variables are then obtained from the configuration database for four
different cases. The variable() function is used to obtain an RTRConfigVariable reference. The
parameters on the variable() function call are:
• the Class Identifier which identifiers the type of the component that is to match an entry in the
configuration database
• the Instance Identifier which identifies a particular instance of a component
• the name of the variable

SFC Developer’s Guide 247


4.8 SFC MODELS

• a default value that is returned if a variable cannot be found in the database that matches either of
the identifiers
Note that the query for "var4" does not provide a default value. The returned variable must therefore
be checked for an error.
#include "rtr/rtxfdb.h"

int main()
{
RTRXFileDb configDb("./config_file");
if (!configDb.error())
{
// Example of full expanded name
RTRConfigVariable var1 = configDb.variable(
"RequestQueue",
"machine2.sink_distributor.request_queue",
"queueSize",
"500");
// Example of wildcarded id
RTRConfigVariable var2 = configDb.variable(
"RequestQueue",
"machine30.sink_distributor.request_queue",
"queueSize",
"500");
// Example of using default value
RTRConfigVariable var3 = configDb.variable(
"SessionManager",
"mySessionClient.session_manager",
"maxSessions",
"30");
// Example of no default and no value
RTRConfigVariable var4 = configDb.variable(
"RrmpManager",
"machine22.V301.sink_distributor.rrmp_manager",
"rrmpAddress");

cout<<"Value of variable ‘var1’ is ‘";


cout<<var1.value().to_c()<<"‘"<<endl;

cout<<"Value of variable ‘var2’ is ‘";

SFC Developer’s Guide 248


4.8 SFC MODELS

cout<<var2.value().to_c()<<"‘"<<endl;

cout<<"Value of variable ‘var3’ is ‘";


cout<<var3.value().to_c()<<"‘"<<endl;

if (var4.error())
{
cerr << "Error: No value for ‘var4’" << endl;
}
}
else
cout<<"Config db error: "<<configDb.errorText()<<endl;
}
Given the following configuration file entries in file./config_file:
machine2.sink_distributor.request_queue.queueSize : 1000
*queueSize : 200
the program output is:
Value of variable ‘var1’ is ‘1000’
Value of variable ‘var2’ is ‘200’
Value of variable ‘var3’ is ‘30’
Error: No value for ‘var4’
The value of var1 is 1000 because it matches.
Configuration variable var3 shows how the default value is used if a value cannot be found in the
configuration database.
Configuration variable var4 is returned with error() set to True because no value is found in the
configuration database and no default value was provided.

4.8.5.6 An Implementation Using the Microsoft Windows NT Registry


On the Microsoft® Windows NT™ operating system, the registry stores all system, application, and
user configuration information. A user or administrator usually does not access the registry directly,
although they can using the Registry Editor (regedt32.exe). However, improper use of this tool can
damage the system configuration settings and prevent the operating system from starting or running
properly. Therefore, each application should provide a user interface to view or edit important
configuration settings.

SFC Developer’s Guide 249


4.8 SFC MODELS

The SFC provides an implementation of RTRConfigDb called RTRRegistryDb which applications can
use to access configuration data in the registry. This implementation provides the RTRConfigDb
interface for reading configuration variables from the database and also provides new functions to
allow writing values for variables into the configuration database.
The convention for storing software configuration information in the registry is to store configuration
values in a tree in the HKEY_LOCAL_MACHINE hive whose key name is of the form:
SOFTWARE\<Vendor>\<Application>\<Version>
The hive and key name may be specified by the application programmer when creating an instance of
RTRRegistryDb (or the default values of HKEY_LOCAL_MACHINE and
SOFTWARE\Reuters\SFC\CurrentVersion may be used). Within this tree, RTRRegistryDb uses two
separate sub-trees with key names Class and Instance to store values for configuration by class and
instance, respectively.
When a configuration variable is accessed from the RTRRegistryDb, the specified class and instance
object ID names for the variable are converted to key names using backslashes to separate the
components of the object ID names. These key names are then used as sub-keys in the registry
configuration tree under the Instance and Class sub-trees.
When a variable is retrieved using the variable() function, the Instance sub-tree is searched before the
Class sub-tree.

4.8.5.7 RTRRegistryDb Example


The following sample program shows the use of the RTRRegistryDb implementation of the
configuration database to access values stored in the registry. This small program creates an instance
of RTRRegistryDb, specifying that the application data will be stored in the HKEY_LOCAL_MACHINE
hive in the tree whose key is SOFTWARE\MyCompany\MyApplication\CurrentVersion. A configuration
variable is obtained from the configuration database, a new value for the configuration variable is
written to the database, and the variable is then read from the database again to show that the value
has changed.
The variable() function is used to obtain an RTRConfigVariable reference. The parameters on the
variable() function call are:
• the Class Identifier which identifiers the type of the component that is to match an entry in the
configuration database
• the Instance Identifier which identifies a particular instance of a component

SFC Developer’s Guide 250


4.8 SFC MODELS

• the name of the variable


• a default value which is returned if a variable cannot be found in the database that matches either
of the identifiers
The putInstanceVariable() function is used to write a new value into the configuration database. The
parameters on the putInstanceVariable() function call are:
• the Instance Identifier which identifies a particular instance of a component
• the name of the variable
• the value
#include "rtr/regdb.h"

int main()
{
RTRRegistryDb configDb(HKEY_LOCAL_MACHINE,
"SOFTWARE\\MyCompany\\MyApplication\\CurrentVersion");
if (!configDb.error())
{
// Retrieve initial configuration value
RTRConfigVariable var1 = configDb.variable("RequestQueue",
"machine2.sink_distributor.request_queue", "queueSize", "500");
cout<<"Value of variable ‘var1’ is ‘";
cout<<var1.value().to_c()<<"‘"<<endl;

// Put new configuration value into database


configDb.putInstanceVariable(
"machine2.sink_distributor.request_queue",
"queueSize", "600");

// Retrieve new configuration value


var1 = configDb.variable("RequestQueue",
"machine2.sink_distributor.request_queue", "queueSize", "500");
cout<<"Value of variable ‘var1’ is ‘";
cout<<var1.value().to_c()<<"‘"<<endl;
return 0;
}
else
{

SFC Developer’s Guide 251


4.8 SFC MODELS

cout<<"Config db error: "<<configDb.errorText()<<endl;


return 1;
}
}
Assuming that the following entry has been created in the registry under the key using the Registry
Editor (regedt32.exe):
Key Name:HKEY_LOCAL_MACHINE\SOFTWARE\MyCompany\MyApplication\CurrentVersion\
Instance\machine2\sink_distributor\request_queue
Value Name: queueSize
Data Type: REG_SZ
String: 300
the program output is:
Value of variable ‘var1’ is ‘300’
Value of variable ‘var1’ is ‘600’

NOTE: Unlike file configuration variables, which permit wildcarding, registry configuration variables
must be fully specified. For example the configuration variable logger.defaultFileAction.selector can be
set in a file as:

*logger*selector: *.debug

In the registry, the full variable name:

\\HKEY_LOCAL_MACHINE\SOFTWARE\MyComp\MyApp\Version\logger\defaultFileAction\selector

must be used.

4.8.5.8 Global Access using RTRConfig


The class RTRConfig provides global access to the current configuration database by means of static
member functions. The class is designed to provide simplified and consistent access to the
configuration database. RTRConfig provides methods to both set and retrieve the current database.
Unless specifically overridden, RTRConfig provides access to an instance of RTRDefaultConfigDb.

SFC Developer’s Guide 252


4.8 SFC MODELS

4.8.6 Event Logging

4.8.6.1 Overview
The event logging cluster addresses the problem of allowing components to generate events without
being concerned with application context. For example, it may not be appropriate for a library
component to arbitrarily print error messages on the standard error device. Application designers may
want those errors to be displayed somewhere else, perhaps in a dialogue box of a windowing system.
The event logging cluster provides an extensible event logging mechanism which allows the
application designer to decide how events are handled.
The class representing an event is RTRMgmtEvent. Components allocate instances of
RTRMgmtEvent and assign it identity, severity and text. The event can then be logged as necessary.
The component generating the event does not determine what to do when the event is created.
"Actions" are objects which decide how to process events. For example, a file action could write an
event to a log file, and a stderr action could write a message on the standard error device.
An application has a single instance of an event router. This centralized component is informed by an
event when it needs to be distributed. The router passes the events to all actions that have registered
with it.
Actions choose which events they will process with a filter. An action’s filter keeps track of a list of
"selection pairs". A selection pair consists of a component name and a severity level. The selection
pair list defines the log events that the log action instance will process. To generate a match, the
component name of the selection pair must match the identity of the component generating the event.
In addition, the severity level of the selection pair must match the severity level of the even
The identity used in generating log events is an arbitrary value set by the designer of the component.
The technique used in assigning instance identities in configuration (section 4.8.5.3) is also
appropriate for logging events. Severities have one of the following values (listed from lowest severity
to highest):
1. Debug
2. Info
3. Notice
4. Warning
5. Error

SFC Developer’s Guide 253


4.8 SFC MODELS

6. Critical
7. Alert
8. Emergency

NOTE: Events are logged for all events that are the specified severity level and higher. So, if the
Info severity level is specified, all events will be logged except Debug events.

Through the use of wild-carded selection pairs, actions can be configured to trap log events in a
number of ways:
• from a particular component with any type of severity
• from all components with a specific severity (and higher)
• from a particular component and severity pair
• or from all components and all severity types

4.8.6.2 Implementation Classes


The RTRDefaultLogger class is a utility that instantiates and installs two actions: a file action and a
stderr action.

4.8.6.3 Simple Example


The following example shows how a typical client application would utilize log events. In the main() of
the client application, an instance of RTRDefaultLogger is created. Note that a configuration database
is also created and installed. Assuming that the default configuration is used with this default logger, a
file log action is automatically created and installed in the event router. This default file log action is set
up to log all events that have severity level values from "Info" to "Emergency", inclusive.
#include "rtr/rtxfdb.h"
#include "rtr/dfltlog.h"
#include "rtr/config.h"

int main()
{
RTRXFileDb configDb("./config");
RTRConfig::setConfigDb(configDb);

SFC Developer’s Guide 254


4.8 SFC MODELS

RTRDefaultLogger logger("application_name", "logger", "application_name");


...
}
At this point, the default logger contains a file log action. A component class can use the default logger
by including the appropriate header, creating a log event, setting up the log event, and logging a
message as follows:

#include "rtr/mgmtevnt.h"

MyClass::doSomething()
{
RTRMgmtEvent logEvent;

// Set up the component name, text and severity of


// the log event.
logEvent.setComponent("my_component_name");
logEvent.setText("This is a critical message to be logged");
logEvent.setSeverity(RTRMgmtEvent::Critical);
logEvent.log();
}
Given that the configuration file was empty and the default actions were installed, then the following
message will appear in the file log.out when method "MyClass::doSomething" is invoked:
<my_component_name: Critical:Fri Mar 25 14:30:30 1994>
This is a critical message to be logged
<END>

4.8.6.4 Configuration Examples


This section shows several different ways to configure the RTRDefaultLogger. There are quite a few
configuration variables for the various logging components. The intent of this section is to provide a
number of typical configurations. These examples assume that an instance of RTRDefaultLogger
exists in the system and that the configuration database it uses is based on the particular configuration
file example.
For each of the sample configurations, the instance ID of the default logger will be "logger". The
instance ID of its file logger is always "defaultFileAction", and the instance ID of its stderr action is
always "defaultStdErrorAction".

SFC Developer’s Guide 255


4.8 SFC MODELS

• Configuration file for a system with a default file action and a default stderr action:
logger.install_stderr_logger: True
By adding this line to the configuration file, the default logger will automatically create and install a
default stderr action to go along with the default file log action. Since there are no special
configurations for either the file action or the stderr action, some special default characteristics
specific to these default log actions are put into place. Specifically, the stderr action and file action
will each process log events for any component name and for severity levels "info" to
"emergency".
The other default configuration options for default logger’s file action are shown in the following
table.

Variable Name Type Default Use

max_bytes integer 10000 The file size which, when exceeded, will cause
the file to be saved to a ".old" file

truncate boolean False If True, an existing log file will be truncated

file string log.out The pathname of the log file

flush boolean True Enable/disable the flushing of output immediately


after writing

The other default configuration options for both default logger’s stderr action and default logger’s
file actions are shown in the following table.

Variable Name Type Default Use

priority integer 100 Sets the priority of this action with respect to
other actions

enable boolean True Enables/disables this action

SFC Developer’s Guide 256


4.8 SFC MODELS

Variable Name Type Default Use

selector list N/A A comma separated list of instance/severity "dot"


pairs which define the matching criteria for events
on which this action should act. All events higher
than the lowest severity level will be logged.

• Configuration file for a system with only a default file action and with selector overrides and
overrides for log file name and log file size:
*logger.defaultFileAction.file: /var/triarch/my_log_file
*logger.defaultFileAction.max_bytes: 100000
*logger.defaultFileAction.selector: *.info
This configuration causes the default logger to create and install a file action that uses the file
/var/triarch/my_log_file to log event text, sets the maximum number of bytes the file will contain
to 100,000, and accepts log events that are from any component and have a severity of "info" or
higher.
• Configuration file for a system with only a default stderr action with selector overrides:
*logger.install_file_action: False
*logger.install_stderr_action: True
*defaultStdErrorAction.selector: *.*
With this configuration, the default logger will automatically create and install a stderr action that
will accept log events that are from any component and have any severity. Notice that the "*"
notation is used with the instance ID of the stderr action configuration.
• Configuration file for a system with win32 event logging:
*install_system_action: True
This configuration allows you to monitor SFC’s events via Windows event viewer.

4.8.7 Command Line

4.8.7.1 Overview
The command line classes are utility classes that make it easier to specify and parse command line
arguments. They are used extensively in the example programs. All of the command line classes

SFC Developer’s Guide 257


4.8 SFC MODELS

begin with RTRCmdLine-. The base class representing the entire command line is RTRCmdLine. Only
one RTRCmdLine will be in an application, so the static variable RTRCmdLine::cmdLine should be
used to access it.
All of the command line arguments are descendent from RTRCmdLineArg. They can be strings,
numerics, flags, or a list. Each command line variable consists of a tag, a name, a purpose. For some
types of variables, a default value must be specified. By default, all variables are required, although
variables can be made optional using an extra argument in the constructor. When a variable is
specified on the command line, its tag should be pre-pended with ‘-’. See section 4.8.8.6 for more
information on the type of command line arguments. See the SFC Reference Manual for more detailed
information about the classes that implement the various types for command line arguments.
The RTRCmdLineFlag -? is always included in RTRCmdLine. When the -? command line argument is
specified, usage information for the application will be printed. This information is derived from the
tags, names, and purposes specified in the command line variable constructors.

4.8.7.2 Usage
Five typical steps are taken when using the command line model.
1. Declare the static RTRCmdLine::cmdLine.
2. Declare and specify all of the command line variables.
3. Call RTRCmdLine::cmdLine.resolve(argc, argv).
4. Check the command line proper usage.
5. Access each variable’s typed data.
The following example code shows the steps listed above.
#include <iostream.h>
#include "cmdline.h"
RTRCmdLine RTRCmdLine::cmdLine; // Create static first
//other includes

int main(int argc, char **argv)


{
RTRCmdLineString string("config", "file_name", "config file");
RTRCmdLineFlag flag("d", "enable debug");
RTRCmdLineNumeric i("instance", "#", "instance number to use", 1);
RTRCmdLineList files("files", "input files");

SFC Developer’s Guide 258


4.8 SFC MODELS

RTRCmdLine::cmdLine.resolve(argc, argv);
if ( RTRCmdLine::cmdLine.error() )
{
RTRCmdLine::cmdLine.printUsage(cerr, argv[0]);
return -1;
}
cout << "outFiles are ";
const RTRDLinkList<RTRCmdLineData, RTRDLink0>& l = files.values();
for (RTRCmdLineData *d = l.first(); d; d = l.next(d) )
{
cout << *d;
if ( d != l.last() )
cout << ",";
}
cout << endl;
return 0;
}
For this example, the command:
a.out -d -config config.cnf -i 24 file1.txt file2.txt file3.txt
would result in debugging on, config.cnf used as a configuration file, 24 as the instance number, and a
file list that includes file1.txt, file2.txt, and file3.txt. Note that the ‘-d’ command line flag does not have a
sub-argument. When a command line flag is followed immediately by another command line
argument, its sub-argument is optional.
The command line arguments can be in any order. The following command is equivalent to the first.
a.out -config config.cnf -d true file1.txt file2.txt file3.txt -i 24
Note that all extra arguments (file*.txt) are added to the list. The ‘true’ sub-argument for -d is needed to
make sure file1.txt is not picked up as the optional sub-argument of -d.

4.8.8 Class Summary

4.8.8.1 Connection
• RTRMDConnection - This class is the abstract base class for implementing connections to
market data infrastructure.

SFC Developer’s Guide 259


4.8 SFC MODELS

• RTRMDConnectionClient - This class defines the interface by which a subclass can receive
state and informational events about an RTRMDConnection.
• RTRTIBConnection - This class encapsulates a Rendezvous session. RTRTIBConnection is
also listens to all advisory messages.
• RTRSSLConnection - This class encapsulates a connection to an upstream SSL component.
• RTRSSLConnectionServer - This class encapsulates a well-known listen port.
RTRMDConnectionClients are notified if a DACS connection is lost or established.

4.8.8.2 Service Pool Factory


• RTRMDServicePoolFactory - This class defines the abstract interface for service pool factories.
Service pool factories are designed to make it easy to create and manage multiple services over
the same connection. So, service pool factories will often create implementation objects
automatically as they are needed.
• RTRTIBServicePoolFactory - This implementation of RTRMDServicePoolFactory knows how to
connect to an RMDS infrastructure with a TIBCO Rendezvous Distribution Layer and install
services. RTRecord, Page, and TimeSeries services pools are all supported. RTPage services
are not supported on an RMDS infrastructure with a TIBCO Rendezvous Distribution Layer, so
use Page services instead. TIB services cannot be dynamically loaded.
• RTRSSLServicePoolFactory - This implementation of RTRMDServicePoolFactory knows how
to connect to an SSL infrastructure and dynamically install services. RTRecord RTPage, Page,
and TimeSeries services pools are all supported. By default, all service pools are loaded
dynamically.
• RTRCompositeServicePoolFactory - This implementation of RTRMDServicePoolFactory
aggregates service pools from multiple service pool factories into a single service pool.

4.8.8.3 Control Loop


• RTREventNotifier- This is the abstract base class for the application control loop. Application
components which are descendants of RTRIOClient can register with the notifier to receive I/O
events.
• RTRIOClient - This is the abstract base class for application components which wish to register
with the control loop in order to receive I/O notification events.

SFC Developer’s Guide 260


4.8 SFC MODELS

• RTRTimerCmd - This is the abstract base class for timers, i.e. commands which will be executed
after a specified interval.
• RTRSelectNotifier - This is an implementation of a control loop based on the select() system
call.
• RTRXtNotifier - This is an implementation of a control loop which uses the facilities provided by
the Xt library.
• RTRXViewNotifier - This is an implementation of a control loop which uses the facilities provided
by the XView library.
• RTRWindowsNotifier- This is an implementation of a control loop which uses facilities of the
Windows API.

4.8.8.4 Configuration
• RTRConfigDb- This is the abstract base class for a database of configuration variables.
Variables are accessed by means of three keys: the class identifier of the requesting component,
the instance identifier of the requesting component, and the name of the variable. An additional
parameter, the default value to be assigned to the variable, is optional.
• RTRConfigVariable - This descendant of RTRString (via RTRExternalValue) is the basic unit of
configuration. A configuration variable accessed from the database will be in an error state if a
value has not been explicitly configured and no default is provided. A configuration variable
provides various mechanisms by which the underlying data may be converted to some other
form.
• RTRObjectId - This class is used for both class and instance identifiers. It is can be thought of as
a compound string.
• RTRExternalValue - This descendant of RTRString is an ancestor of RTRConfigVariable and
provides the means to transform the underlying data into other representations, e.g., into a list of
values based on a given delimiter.
• RTRListOfExternalValue - This class is the result of interpreting a configured value as a
delimited list of values.
• RTRConfig - This class provides static functions which allow access to a "global" configuration
database. Unless otherwise specified by the application, the database to which access is
provided is of type RTRDefaultConfigDb.

SFC Developer’s Guide 261


4.8 SFC MODELS

• RTRXFileDb - This implementation of RTRConfigDb loads an X resources style file of


configuration information.
• RTRRegistryDb - This implementation of RTRConfigDb is implemented to use the Windows NT
registry database.
• RTRDefaultConfigDb - Variables from this database have default values, where given; otherwise
the variable is returned in an error state. This version of the database is typically used in simple
programs where configuration is not required and default values are appropriate.

4.8.8.5 Event Logging


• RTRMgmtEvent - Application components use this class to generate log events which are then
processed by the centralized event logging mechanism.
• RTRDefaultLogger - This utility class instantiates one default file action and one default stderr
action. The matching criteria of the actions are set by default to trap everything except debug
messages. This behavior can be changed via configuration variables.

4.8.8.6 Command Line


• RTRCmdLine - All command line variables register with an object of this. Then this class will
parse argc and argv, assigning the appropriate values to each command line variable.
• RTRCmdLineString - A simple command line variable that takes a single sub-argument. This
variable can be cast to a RTRString.
• RTRCmdLineList - When a RTRCmdLineList is used, all command line arguments not assigned
to another command line variable are added to this list. A RTRCmdLine can only have one
command line list.
• RTRCmdLineNumeric - This command line variable takes a single sub-argument, which must be
a number. The sub-argument is type-checked and can be cast to a long.
• RTRCmdLineFlag - This command line variable can take a single sub-argument, which must be
true or false. The variable can be cast to a RTRBOOL. If the flag is specified without a sub-
argument, it defaults to RTRTRUE.

SFC Developer’s Guide 262


4.8 SFC MODELS

4.8.8.7 International Characters


• RTRUTF8String - This class provides a convenient and efficient way for applications to represent
RMTES, Unicode, and ASCII characters in UTF-8 format.

SFC Developer’s Guide 263


5 SFC IMPLEMENTATION DETAILS
5.1 SSL and TIB Implementations
SFC has two implementations (TIB and SSL) that support two infrastructures (RMDS and Triarch). The
RMDS infrastructure consists of the RRDP Market Data Hub along with a TIBCO Rendezvous
Distribution Layer. The TIB implementation can be used with the RMDS infrastructure along with a
TIBCO Rendezvous Distribution Layer. The SSL implementation can be used with the Triarch
infrastructure and with the RRDP Market Data Hub in the RMDS infrastructure. This chapter discusses
some of the differences between the infrastructures and provides details for some important
implementation and usage issues.
Implementation information about publishing services can also be found in section 4.2.4 and Table 4.9.
These documents may be useful in helping to more fully understand these issues and the context in
which they are found:
[1] Reuters SSL 4.1 Architecture Overview - DocID: SSL411SD.990
or Core RMDS Distribution Architecture , June 2001
[2] SSL Infrastructure 4.1.2 Software Installation Manual - DocID: SSL412IP.000
or Reuters Market Data Hub - Source Infrastructure 4.2 Software Installation Manual - DocID:
SSL420IP.010
[3] DACS 5.2 Reference Manual - DocID: DACS520UM.040
[4] TIBCO Information Cache Administrator’s Guide -Software Release 10.0.3- System Release
4.1.0, March 2001
[5] TIB Entitlements Administrator’s Guide - Software Release 6.2.9 - System Release 4.0.1,
September 2000
[6] CMON/DQA System Administrator’s Guide - Software Release 2.1.0 - System Release 4.0.1,
September 2000
[7] TIB/Rendezvous Administrator’s Guide 6.7, June 2001
[8] TIB/Rendezvous Concepts 6.7, June 2001
[9] Selectfeed Plus User Guide or Selectserver User Guide (for information on the construction
of Reuters Instrument Codes)
[10] Marketlink Contribution Server Administrator’s Guide - Software Release 3.2.0 - System Re-
lease 3.9 , March 1998

SFC Developer’s Guide 264


5 SFC IMPLEMENTATION DETAILS

5.2 Implementation Classes


Typical SFC applications will only need implementation-specific code in one place. This code consists
of the initialization process that connects to an infrastructure and creates services. So, most of the
SFC implementation classes never need to be used. The following table lists some of the useful
implementation classes. It also shows the correlation between TIB and SSL implementation classes.
See the SFC Reference Manual for more information on these classes.

Triarch & RMDS Market Rendezvous & RMDS


header header
Data Hub class Distribution Layer class

RTRSSLRTRecordService rtr/sslrtrs.h RTRTIBRTRecordService rtr/tibrtsvc.h

RTRSSLPageService rtr/sslpgsrvc.h RTRTIBPageService rtr/tibpgsrvc.h

RTRRTFieldToSSLRecordService rtr/fldtossl.h RTRRTFieldToTIBRecordService rtr/fldtotib.h

RTRSSLServicePoolFactory rtr/sslsplf.h RTRTIBServicePoolFactory rtr/tibsplf.h

RTRSSLConnection (sub) rtr/sconnect.h RTRTIBConnection (sub & pub) rtr/tconnect.h


RTRSSLConnectionServer (pub) rtr/sslconns.h

RTRSSLDispatcher rtr/ssldisp.h N/A N/A

N/A N/A RTRTIBCustomizer rtr/tibcus-


tomizer.h

RTRSSLFidDb (network) rtr/sslfiddb.h RTRTIBFidDb rtr/tfdb.h


RTRFileFidDb (file) rtr/ufdb.h

RTRSSLInsertService rtr/sslinsrt.h RTRRTFieldToTIBRecordService (TIB) rtr/fldtotib.h


RTRTSAInsertService (RMDS) rtr/tsaisrvc.h

Table 5.1: Useful SFC Implementation Classes

SFC Developer’s Guide 265


5 SFC IMPLEMENTATION DETAILS

5.3 Entitlements
The SFC has the ability to interact with a permissioning system to ensure that users can only access
data for which they are entitled. By default, this capability is disabled. If a permissioning system is
available at your site, your SFC applications will need to be enabled to take advantage of entitlements
support. See section 5.3.2 for details on enabling entitlements.
There are several different types of entitlements that are supported by the SFC. Following is a
description of each type:
• User Based Entitlements - This type of entitlement determines if the user is allowed to gain
access to any infrastructure resources. The application is not allowed to access any services until
the SFC has successfully “logged in” with the permissioning system. SFC services will remain in
the stale state until the login occurs. Each user has a profile which determines a user’s level of
entitlements. A username is passed to the permissioning system to match the application with the
proper entitlements profile. See section 5.3.3 for details on how the username is set in an SFC
application.
• Subject Based Entitlements (SBE) - This type of entitlement determines if the user is allowed to
access data from or publish/insert data to a particular data service and data item based on the
user’s profile. Examples of services are specific feed handlers or third party publishing
applications. An example of a data item is the quote data for the symbol “IBM” from the NYSE
exchange. Just before the item is to be requested from the infrastructure, the subject based
entitlement check will be made. If the check fails, an Inactive event is propagated to the
subscriber indicating that entitlements are denied. In the case of publishing applications, a
message is logged indicating that the item cannot be published. In the case of inserts, an
InsertNak event is propagated to the insert initiator.
• Content Based Entitlements (CBE) - This type of entitlement determines if the user is allowed to
access a particular data service and data item based on entitlement data specific to that data
item. The entitlement data typically contains codes that map into various entitlement categories,
such as products, exchanges or vendors which are set up in the permissioning system database.
The permissioning system is able to use the codes to check whether a given user is allowed to
access the data item based on their entitlements in each category. The entitlement data is
received from the infrastructure in conjunction with an image. The content based entitlement
check is done before the image is forwarded to the subscriber. If the check fails, an Inactive event
is propagated to the subscriber indicating that entitlements are denied.

SFC Developer’s Guide 266


5 SFC IMPLEMENTATION DETAILS

• Publishing Entitlement Data - This is not so much an entitlement type as it is a mechanism used
by publishing applications to provide entitlement data to downstream infrastructure clients for use
in CBE checks. Entitlement data is provided before the initial image so that CBE checks can be
performed before image data is processed. See section 4.2.2.11, Publishing Entitlement Data, for
details. For information on how to create DACS access locks, refer to Appendix G, DACS
LIBRARY FUNCTIONS.
In most cases, the entitlement checks occur within the SFC library at the desktop using profile data
that is obtained from the permissioning system at start-up. The profile data is cached in the SFC library
for quick access. In the case of SSL subscription, the entitlement checks occur in the Triarch
infrastructure.
The DACS permissioning system is supported with the RMDS infrastructure (RRDP Market Data Hub
and RMDS Distribution layer using SASS3) and the Triarch infrastructure.

5.3.1 Supported Configurations


The types of entitlements supported in a given SFC implementation will depend on the infrastructure
and protocol being used. Table 5.2 shows which permissioning system and entitlement type is
supported by each SFC implementation. A blank indicates that the feature is not applicable. "N/S"
indicates that the feature is not supported.

SFC Developer’s Guide 267


5 SFC IMPLEMENTATION DETAILS

SFC-supported User Subject Content Publish


Infrastructure Based Based Based Data3

RMDS SASS3 subscription DACS DACS DACS1

RMDS SASS3 publication DACS DACS DACS4

RMDS SASS3 inserts DACS DACS

RMDS Hub publication DACS DACS DACS

SSL subscription2 DACS DACS DACS1

SSL publication DACS DACS DACS

SSL inserts2 DACS DACS

Table 5.2: Supported DACS Entitlements Types in SFC


1. DACS Access Lock entitlement data is used for content based permissioning
with DACS.
2. DACS entitlements is performed in the Sink Distributor.
3. Due to restrictions in the DACS permissioning system, it is not possible for a
publishing application to both publish entitlement data and use subject based
entitlements to control which items are published.
4. Capable with RTIC 11.1 or newer.

5.3.2 Enabling Data Entitlements in SFC


In the SFC, permissioning system access is handled in the RTRMDConnection class. The particular
permissioning system used by the connection is tied to the infrastructure and protocol type; DACS is
used for all RMDS and Sink Distributor.
Since the RTRTIBConnection, RTRSSLConnectionServer and RTRSSLConnection classes inherit
from the RTRMDConnection class, each class uses the same mechanism for enabling data
entitlements.
By default, data entitlements are disabled for RMDS (SASS2) but can be enabled either through SFC
configuration files or by application code through methods available in the connection classes.

SFC Developer’s Guide 268


5 SFC IMPLEMENTATION DETAILS

By default, data entitlements are enabled for SSL publication and RMDS (SASS3), but can be disabled
either through SFC configuration files or by application code through methods available in the
connection classes
To enable or diasble entitlement through configuration, use the following parameter in the SFC
configuration file *enableEntitlements with a value of "True" or "False" (case insensitive). (See section
5.5.10.1 and 5.5.10.2.)
To enable or disable entitlements programmatically, explicitly create a connection and pass it to the
service or service pool factory:
RTRObjectId appId("appId");
RTRTIBConnection connection(appId, "connection");
//to disable entitlements the following line
//should be RTRFALSE
connection.enableEntitlements(RTRTRUE);
connection.connect();
RTRTIBRTRecordService service(appId, "RSF", connection);
The RTRMDConnection base class has an entitlementsEnabled() state attribute. This attribute has
different semantics for the SSL than for RMDS or TIB implementations. On RTIC-based RMDS, this
attribute reflects whether entitlement checking will be performed in the SFC or not. On SSL
subscription, this attribute has no meaning since all subscription entitlements are performed in the
Triarch infrastructure.
In the RTRTIBConnection and RTRSSLConnectionServer classes, the
enableEntitlements(RTRBOOL) method is available in both classes to enable or disable entitlement
checking for that connection. Entitlements can also be enabled through configuration with the
*enableEntitlements variable.
When entitlements are enabled for TIB implementations, the SFC services will remain in a Stale state
and will not request data until connection has successfully logged the user into the permissioning
system. The login process is initiated when the connect() method is invoked on an instance of
RTRTIBConnection or RTRSSLConnectionServer.
When entitlements are enabled for TIB implementations, the system will block until all entitlements
information is loaded in from the permissioning system. This entitlement profile from the permissioning
system is loaded after the data dictionary is complete. This means the connect() call will block and
SFC services will not be available during that time.

SFC Developer’s Guide 269


5 SFC IMPLEMENTATION DETAILS

5.3.3 Setting the Username


In any environment where the DACS permissioning system is in use, the SFC library must have a valid
username to pass to the permissioning system. The username consists of several informational
elements including the machine name where the application is running, an application identifier and
the name of the user running the application. The username is used by the permissioning system to
associate an entitlement profile with this application so entitlement checks can be performed on all
SFC item accesses.
In typical usage, the username is determined automatically in the SFC, with default values obtained
from the operating system (like hostname and username). However, some or all of the elements found
in the username can be also be set from application code or via configuration.
For convenience, this username can be set on many of the SFC service constructors. If an application
creates its own RTRSSLConnection, RTRTIBConnection or RTRSSLConnectionServer, the username
can be set directly using the username(const char *) method any time before the connect() method
is called. The username can also be set through configuration using the “*username” configuration
variable.
The username is a null-terminated character string that is used to convey entitlement information. The
string is composed of several fields delimited by the ‘+’ character. The string format is defined as
follows using BNF notation:
<user_name> ::=
<User_name> |
<User_name>+<Application_ID> |
<User_name>+<Application_ID>+<Position>
More fields may be defined in the future. They will be appended to the end of the string in a similar
manner. The string should not contain any extraneous white space characters.

NOTE: Backus-Naur Form (BNF) notation consists of the following symbols:


<> encloses token elements
+ concatenates elements
| exclusive OR
::= is assigned to

The User_name field identifies a particular person who has been assigned a unique name for access
to the infrastructure (e.g., “E_DICKINSON”). The SFC does not attempt to verify the supplied name

SFC Developer’s Guide 270


5 SFC IMPLEMENTATION DETAILS

beyond ensuring that the name corresponds to an actual user. The length of the User_name field must
not exceed 255 characters. If this field is omitted, the SFC assigns the default user name which is the
name that the owner of the current process used to log into the operating system. This default is
suitable for most applications. The explicit specification of the user name is needed mainly for
applications that handle multiple users in a single process.
The Application_ID field provides the identity of the SSL application. The application ID must be an
integer in the range 1 to 511. The SFC will verify that the application ID is in this range.
Application IDs are assigned by the Reuters International Product Manager for Entitlements. A unique
ID should be obtained if the application is to be used at more than one client site. For site-specific
applications, select any ID in the range 257-511. If this field is omitted, the SFC assigns the default
application ID number, which is 256.
In the case of a single user running the same application on the same machine, the Position field can
be used to uniquely identify the sink application. The length of the Position field must not exceed the
239 (255 - 16. Note that 16 bytes must be reserved for the IP address, which is added to this field by
the SFC.) If this field is omitted, the SFC assigns the default Position “net”. The Position is used in
conjunction with the IP address of the machine on which the process is running to check entitlements
based upon physical location.
Some examples of valid UserName strings are as follows:
1. V_Kandinsky+7+13”
This means the user V_Kandinsky is running application number 7 on position 13 of this
machine.
2. “C_Monet+7”
User C_Monet is running application number 7; the position takes the default value.
3. “+8”
The user name takes the default value. The application ID is 8. The position takes the default
value.
4. “”
The user name, application ID, and position all take the default values. This is the most
common usage.

SFC Developer’s Guide 271


5 SFC IMPLEMENTATION DETAILS

5.3.4 Publishing DACS Access Locks


With this version of SFC, some configuration is necessary to ensure that your DACS formatted
entitlement data will be published properly to the RRDP Market Data Hub (Source Distributor).
Specifically, the SFC library needs to have a mapping of service names to service identifiers. This
mapping can be supplied either by configuration for simple cases or by directly installing a map entry
into the SFC for locks created by different services.

WARNING: If a mapping does not exist for the services associated with a given DACS access lock,
the entitlement data will not be published and an error message will be logged in the SFC log file.

If your publishing application is creating its own DACS access locks, your application must pass to the
DACS access lock creation function the same service type (also called service ID) that is used by the
DACS system for your published service name. This service type is embedded into the access lock
and is used by subscription applications to make CBE checks against that service. The administrator
for the DACS system sets the service ID.
Furthermore, the service mapping table in the SFC must contain a mapping for that service ID to the
name of the published service. This is required by the SFC so the access lock can be translated into a
format acceptable by the Source Distributor. Your publishing application has several options for setting
the service ID/service name mapping entry.
• Allow the SFC to automatically add the mapping entry via configuration variable.
This will only work if the DACS access locks were created with a service ID that maps to the
service name that is being published to the Source Distributor. The SFC will look for the entry
"*<service_name>*serviceId : <id>" in the SFC configuration file, where <service_name> is the
name of your published service and <id> is the service ID associated with that service name in
the DACS system and in the Source Distributor.
An example configuration entry is "*MY_SOURCE*serviceId : 123". This same service ID must
also be set in the Source Distributor configuration file for the service name "MY_SOURCE".
• Add one or more service ID / service name mappings to the SFC directly.
This method should be used if your application does not use the SFC configuration file or if your
DACS access locks contain a service ID that does not map to the same service name that is
being published. For instance, if you create an access lock or compound lock that contains the
service ID 13033 which represents service name "IDN_RSF", but your application is publishing to
service name "MY_SOURCE" which has a service ID of 123 (as determined in the DACS system

SFC Developer’s Guide 272


5 SFC IMPLEMENTATION DETAILS

and the Source Distributor configuration file), then your application needs to add a new SFC map
entry for service ID 13033 and service name "IDN_RSF".
The following code shows how this mapping entry is added to the SFC from application code:
#include "rtr/sslinterface.h"

int serviceId = 13033;


char* serviceName = "IDN_RSF";
RTRServiceIdNamePair* entry = 0;

entry = RTRSSLInterface::ServiceIdMap.getPair(serviceName);
if (entry == 0)
{
cout<< "Adding service map entry for "<< serviceName;
cout<< " and id "<< serviceId << endl;
RTRSSLInterface::ServiceIdMap.addEntry( serviceName, serviceId );
}
else
{
cout<< "Already have entry for " << entry->serviceName();
cout<< " with service id " << entry->serviceId() << endl;
}

NOTE: The service ID used in the SFC service name mapping table must be the same as the ser-
vice ID set in the DACS system and the service ID set in the Source Distributor configuration file for
this published service name. If not set correctly, the published entitlement data will not make it
through the RRDP Market Data Hub.

NOTE: Publishing DACS access lock to RTIC does not need mapping.

5.3.5 DACS Implementation Details


Following are some details regarding the way that DACS is used in the SFC which may be helpful in
understanding the general architecture.
When a RTRTIBConnection or RTRSSLConnectionServer object is created, the connection will
attempt to establish a TCP/IP connection to a DACS Daemon process which is running on the same

SFC Developer’s Guide 273


5 SFC IMPLEMENTATION DETAILS

machine as the application. Once the connection is established, the SFC will attempt a login to the
DACS permissioning system using the information available in the username (see section 5.3.3). If this
succeeds, a profile for that user is passed back to the SFC and cached there. At this point all data
services will become available in the normal fashion, depending on availability from the infrastructure.
As new items are requested, items are published, or inserts are made, the SBE and CBE checks are
invoked and the results handled as described at the top of this section.
If exceptional conditions occur, the SFC will handle them as follows:

Error event SFC Action

Connection to DACS The SFC will automatically attempt to reconnect to the DACS Daemon at
Daemon is lost 60-second intervals. The interval is configurable via the
DACS_retry_connection_interval configuration parameter. While the
connection is down, entitlements checks will continue using the existing
user profile cached in the SFC. Furthermore, by default, no interruption in
data service will be seen. After the reconnection to DACS is successful, all
entitlements will be re-checked in case the user profile has been changed.

The SFC behavior is able to be configured by using new configuration


parameters: *stopSubscriptionWhenDACSDowns and *stopPublica-
tionWhenDACSDowns. The *stopSubscriptionWhenDACSDowns is
for subscription while the *stopPublicationWhenDACSDowns is for pub-
lication and contribution. The default values are False. If the configuration
is set to True, the data service will be interrupted. After the reconnection to
DACS is successful, all entitlements will also be re-checked in case the
user profile has been changed.

Table 5.3: Error Handling of DACS Exception Cases

SFC Developer’s Guide 274


5 SFC IMPLEMENTATION DETAILS

Error event SFC Action

Login to DACS The SFC will automatically retry the login at 1-second intervals. This inter-
Daemon fails val is configurable via the DACS_user_login_retry_interval config
parameter. While the SFC is not successfully logged into the DACS per-
missioning system, no access will be allowed to the infrastructure services.
All subscription services will remain in the Stale state during this time. Pub-
lishing applications will not publish records to the infrastructure during this
time because the connection server will not be activated until the login suc-
ceeds. All insert services will be in the Stale state until the login succeeds.

DACS system The SFC will receive an event from DACS to re-verify all items. Both SBE
changes the profile for and (where feasible) CBE checks will be made. Subscription items that fail
a user the entitlements check will be transitioned to the Inactive state. All publish-
ing items that fail the entitlement check will stop propagating data to the
infrastructure and log a message to the SFC log file. Note that publishing
applications may not receive a notification of this event except for an indi-
cation that no more clients are watching the item. All services that fail the
check will be transitioned to the Stale state as will all items associated with
the service.

DACS system The SFC will receive an event indicating the user login is no longer valid.
un-entitles a user All data services will be transitioned to the Stale state. All data items will be
transitioned to the Stale state with appropriate text indicating that the user
login failed. No attempts are made to re-login. It is up to the application to
do this via the RTRMDConnection::connect() method.

Table 5.3: Error Handling of DACS Exception Cases

5.3.5.1 DACS Thread Aware Option


SFC has bundled DACS 5.2 that thread aware feature is implemented. This allows a multi-thread
process to have SFC embedded within it. Each multi-thread process can perform desktop
permissioning.
To enable the DACS thread aware option, add the following commands to the startup script for the
target process:
DACSAPI_THREAD_AWARE=true; export DACSAPI_THREAD_AWARE

SFC Developer’s Guide 275


5 SFC IMPLEMENTATION DETAILS

For Windows [NT, 2000, XP or 2003], an environment variable can be set at the system level by using
the normal Windows facility for setting environment variables.
Variable Name: DACSAPI_THREAD_AWARE
Variable Value: true

5.3.6 Entitlements Configuration


The following configuration parameters can be used to change the behavior of the DACS entitlements
implementation:
• *<serviceName>*serviceId : This parameter is used to set the service ID value for a particular
service name. This can be used when publishing entitlement data. The SFC requires that a
mapping is available for each service ID that will be found in the entitlements data if that data
uses the DACS access lock format. The <serviceName> must be the name of the service as it is
published to the system. The value of this parameter must match the service type / service ID
found in the DACS access lock and must match the service ID in the DACS database and in the
Source Distributor configuration file for this service name.
• *<serviceName>*serviceID - This is an alternative to the serviceId parameter explained above.
This configuration parameter takes precedence over the serviceId parameter if both exist in the
SFC configuration file. This parameter matches a parameter previously used in the sslapi.cnf by
the SSL ‘C‘ API and remains for compatibility uses. The instanceId parameter should be used in
typical usage scenarios.
• *username - Determines the username that is used by the permissioning system. See section
5.3.3 for details.
• *permField - defines the data field to use to generate DACS lock in a TIB SASS3 infrastructure.
The default value is PROD_CATG.
• *dacsHashTableSize - OBSOLETE. Determines the size of the hash table that holds entries
associated with each item that is currently being watched or published. Increase this value if your
application will be subscribing or publishing to > 1000 items.
NOTE: *number_of_items should be used instead of dacsHashTableSize.
• *DACS_retry_connection_interval - Sets the number of seconds to wait before trying to
reconnect to the DACS sink daemon. The default value is 60 seconds. This value should not be
set too low because attempting to connect to the DACS sink daemon is a blocking call.

SFC Developer’s Guide 276


5 SFC IMPLEMENTATION DETAILS

• *DACS_user_login_wait_period - Sets the number of seconds to wait for a reply to a login


request before giving up. The default value is 60 seconds.
• *DACS_user_login_retry_interval - Sets the number of seconds after a login timeout before
trying to login again. The default value is 1 second.
• *DACS_log_file_size - This parameter is the size that the usage data file can grow too, after
which a message is sent to the DACS Server to pick up the usage file. This parameter is
interparated to be in kilobytes. The default value is 255.
• *DACS_log_file_path - This parameter defines the location where the usage and backup usage
file will reside. The default location is the current directory.
• *DACS_log_flush_interval - Sets how often the DACS log information is flushed to disk. The
default is 60 seconds.
For the RMDS infrastructure, see section 5.5.10 for additional configuration for enabling entitlements.

SFC Developer’s Guide 277


5 SFC IMPLEMENTATION DETAILS

5.4 Performance Tuning and Tracing


SFC’s performance depends on a variety of factors. As with most other computer software, SFC has a
CPU time versus memory space tradeoff. In some instances, SFC also has a CPU time versus cross-
infrastructure compatibility tradeoff. Additionally, SFC’s performance can depend on the type and
configuration of the infrastructure, the responsiveness of the network, and the format of the data. This
section discusses how to manage the tradeoffs and what can be done by the application developer
and the system administrator to maximize SFC’s performance. See section 4.8.3.3 for performance
implications with custom event loops.

5.4.1 General Guidelines

5.4.1.1 Use Libraries Without Assertion


C++ Edition includes two optimized libraries, one with assertions enabled (i.e. the -a libraries) and one
without assertion enabled. The assertion libraries are built with preconditions and post conditions to
help detect when the library is used incorrectly. Some of the assertion checks are very time
consuming, so the assertion libraries should not be used in performance intensive applications.

5.4.1.2 Disable Tracing


For optimal performance, tracing should always be disabled. Tracing is off by default. See section
5.4.6 for details on tracing.
File and stderr logging can also affect performance. Debug-level logging is useful when developing an
application, but it can be overkill for applications that are working. The following configuration will
minimize logging in applications that are working normally:
*selector: *.warning
*install_stderr_action: false
To completely disable logging, do not create a RTRDefaultLogger in the application and set the
following configuration:
*sslLogFileSize: 0

SFC Developer’s Guide 278


5 SFC IMPLEMENTATION DETAILS

5.4.2 Optimizing Code


SFC provides value-added functionality to market data, including request queuing, parsing, caching,
and callback dispatching. While this functionality reduces the work that must be done by the
application, it does take some time. Some of the most expensive operations in SFC are:
• Accessing a market data item from a service
• Accessing a field from a record
• Setting the contents of a field
• Sending an image or an update
Whenever reasonable, SFC applications should try to minimize those operations to improve
performance.

5.4.2.1 Accessing a Market Data Item from a Service


SFC’s data cache improves application performance when the same records are accessed repeatedly
by eliminating the need to re-request the record from the infrastructure. Arbitrary access to a record
involves a hash table look-up using the RIC. While SFC uses an efficient hashing function, the speed
of the hash table look-up depends on the loading factor of the hash table. SFC’s hash tables use linked
lists for collisions, so when the hash table is overloaded, item retrieval is not constant.
If SFC’s performance degrades with a large number of items, then the hash table size may need to be
increased. By default the hash table size defaults to 503 for consuming services and 101 for publishing
services. The hash table size can be configured using the *number_of_items configuration variable.
This variable can be configured on a per service basis by scoping with the service name. For example:
*RSF*number_of_items: 1453
*MY_SERVICE*number_of_items: 142857
Also, this variable can be configured with a specific ClassId (see section 5.6.2). For example:
*TIBRTRecordService*number_of_items: 100000
*SSLPublisherRecordService*number_of_items: 150000
However, configuring *number_of _item per ClassId will be overrided by setting of *number_of_item
and *number_of_items per service.
If RTRRTRecordServiceIterator is used to iterate through all cached records, be sure to use the
fastNext() method instead of forth(). See the Reference Manual for details.

SFC Developer’s Guide 279


5 SFC IMPLEMENTATION DETAILS

When SFC does not have an item cached, the time that it takes to provide data images via sync events
depends on the infrastructure and on SFC’s request queue. If the infrastructure does not have items
cached, then the image rate will be slower and the CPU utilization by SFC will be slower. For
information on how the request queue affects image rates, see section 5.4.4.

5.4.2.2 Accessing a Field from a Record


Applications can improve performance by controlling how and when field lookups are performed.
Deciding the best way to access fields depends on the application’s deployment infrastructures,
design, and memory footprint.
Lookups by FID (i.e. RTRRTRecord::field(int)) are more efficient than by field name (i.e.
fieldByName(const char *)). However, since FIDs are not consistent across infrastructures, using
field names is more portable. If an application is only going to be used in one infrastructure, then FID
lookups can be used.
Alternatively, if a small number of fields are used by an application, it could look up the FIDs for the
field names dynamically at initialization using a RTRFidDb. Then it could cache the FIDs and use them
when processing updates and images for efficiency. For a small number of records, references to the
RTRRTField objects could be maintained in the application.
To avoid field look-ups completely, an application can implement RTRRTFieldClients. Then, SFC will
dispatch field update events to the application during parsing, thereby completely avoiding a field look-
up in the application.
If the application is interested in most of the fields, then RTRRTRecordIterator and
RTRRTRecordUpdateIterator should be used instead of dozens of RTRRTFieldClients. Since the
fields are sorted, the record iterators provide consistent and efficient access to all of the fields.

5.4.2.3 Setting the Contents of a Field


SFC’s RTRField objects store data in a character array. When the publisher changes the data, it must
use one of several set methods to copy the new data into the field. When many fields update very
frequently, data copying becomes one of the most expensive operations in a publisher application.
RTRField provides several set methods, each designed to optimally handle different types of data.
SFC uses all of these methods internally when parsing and caching consumer data:
• RTRField::setData(const char*, int) uses strncpy to write the data directly in a field’s string
storage.

SFC Developer’s Guide 280


5 SFC IMPLEMENTATION DETAILS

• RTRField::set(double) and RTRField::set(int) use sprintf to write numbers into a field’s string
storage.
• RTRField::set(const char *, int) searches the data for character repetition, partial field update,
and RMTES escape sequences. Alphanumeric Marketfeed data may include these escape
sequences. This method is less efficient then setData().
• RTRField::setFromExpandedValue(const char *) is a convenience method that converts an
expanded string to an enumeration integer and then writes the integer to the field’s string storage.
• RTRField::use(char *) is a utility method that can be used for rippling fields efficiently. The char *
argument is swapped for the field’s internal storage. The old storage is returned and the
application must be sure to clean up the field. No data copying is done, so this data is very
efficient. The following code shows how the method can be used to ripple fields:
// RTRRTRecord _record
// RTRRTField * fld; // a field that ripples
RTRRTField * rfld = fld;
char * tmpfld = (char *) fld->to_c();
while (rfld->rippleDefinition())
{
rfld = _record.field(rfld->rippleDefinition()->fid());
if (!rfld)
break;
tmpfld = rfld->use(tmpfld);
}
fld->use(tmpfld);
fld->setData("new data");
After setting a field’s data for an update, the field must be added to a RTRRTFieldUpdateList. This
class includes several methods for adding the field: putFieldByName(const char*),
putFieldByFid(int), and putField(RTRRTField&). putFieldByName(const char *) looks up the FID
and calls putFieldByFid(int), which searches for the field in the record and then calls
putField(RTRRTField&). So putField(RTRRTField&) is the most efficient of the three methods.
RTRRTFieldUpdateList and RTRRTRecordImpl maintain fields in a sorted array. So fields should be
added using putField(RTRRTField&) in FID order whenever possible to avoid resorting.

SFC Developer’s Guide 281


5 SFC IMPLEMENTATION DETAILS

5.4.2.4 Sending an Image or an Update


RTRRTRecordImpl::indicateSync() and RTRRTRecordImpl::indicateUpdateComplete() are
expensive methods because they format a message for the network and send the message to the low-
level communication library (SSL, SASS3, or MDAPI). Depending on the batching features supported
by the low-level library, the message may also be sent to the network during the indicate call.
Image and update messages will not be sent to the network unless the publisher service is up. So to
pre-load SFC’s cache, create all records and call RTRRTRecordImpl::indicateSync() on those
records before calling RTRRTRecordServiceImpl::indicateSync().
When SSL publishers are in source-driven mode, SFC will pace sending images to the network. See
section 5.4.5 for details.
SFC’s SSL and TIB publishing implementations do not require RTRRTField::indicateFieldUpdated()
to be called for updated fields. Publisher applications only need to call that method if a
RTRRTFieldToFieldRecordService is used to publish data in the same process to be used by other
components in the same application.

5.4.3 Reducing Memory Usage


Most of the memory used by an SFC application is from the fields cached for each record. This section
discusses several options for controlling how much memory is used by cache.
Previous versions of SFC used the *fids_per_record configuration variable to set the field array size
of a record. This variable is no longer needed, as SFC will now dynamically size the field array of each
record using the record’s image. Leaving *fids_per_record set to the default (-1) will minimize
memory usage.

5.4.3.1 Use SFC’s Cache


Applications should try to take advantage of SFC’s data cache. SFC’s cache can be leveraged in
several ways:
• if the application design permits, it should not keep its own copy of the data
• use service iterators to access the item in SFC’s cache instead of maintaining a separate
watchlist in the application
• a single object can be a client of multiple market data items

SFC Developer’s Guide 282


5 SFC IMPLEMENTATION DETAILS

5.4.3.2 Reducing Consumer Memory


If all of the applications only need a subset of the data, the infrastructure can be used to filter the data.
All cache applications will have a smaller cache footprint and will also have better performance from
smaller messages.
When a RTRRTFieldClient is added to a RTRRTField, additional storage is allocated for the field. So
memory can be saved by not using RTRRTFieldClients. When the first field client is added to a field,
approximately 32 bytes are used. So using RTRRTFieldClients is only an issue when the application
has thousands of records, each with many field clients.
When Triarch and RMDS consuming applications only need a small percentage of the fields in the
record, but using a filtering component in the infrastructure is not an option, the applications can save
memory by using a custom appendix_a. If a FID definition is not in the appendix_a, SFC will not
cache the field. If a custom appendix_a is used, several guidelines should be followed:
• SFC will create a Notice log event for fields with no definition, so the logging selector should be
set to *.warning to avoid performance degradation.
• Fields removed from appendix_a must also be removed from enumtype.def.
• A custom appendix_a should only be used by the application that requires it. Do not change the
system appendix_a and enumtype.def in /var/triarch. The SFC application can use the
*fid_file_path and *enum_file_path configuration variables to set the location of a private data
dictionary.

5.4.3.3 Reducing Publisher Memory


SFC publishing applications allocate the character arrays used to store field data. Normally, the size of
the allocated array is the FID definition + 1 (for the termination character). If the application knows that
the FID definition is larger than necessary for a particular field (e.g. the DSPLY_NAME is "ZZZ Inc.",
which is much less than the FID definition size of 16), then it could allocate the maximum field size + 1.

5.4.4 Request Queueing and Timing


SFC uses request queuing to avoid thrashing and to ensure that an SFC client application behaves in
a reasonable manner. If a client application requests a large number of items at the same time, the
item images could be returned about the same time. If the client application cannot process the images
fast enough, the network channel will overflow, causing the application to be disconnected. When the

SFC Developer’s Guide 283


5 SFC IMPLEMENTATION DETAILS

client tries to recover, it will again request all of the items, thereby repeating the problem. This situation
is often called thrashing.
Sometimes, requests for valid market data items take a longer period of time, especially when they are
not cached by the infrastructure. SFC uses request timing to ensure that a few slow pending items do
not prevent other queued requests from waiting an unreasonable amount of time.
Many of the properties, such as queue sizes and request time-out intervals, can be customized. Most
client applications can use the defaults. However, depending on factors such as client machine speed
and network bandwidth, some applications may see better behavior by changing the request
properties.
The request queuing and timing implementations are the same for both the SSL and the TIB
implementations of SFC.

5.4.4.1 Request Queue


The request queue is used to queue pending requests which are descendants of RTRRequestItem.
The request queue has a limit on the current number of outstanding requests. This is called the
pending limit. In the SFC, the request queue implementation will adjust its pending limit to maximize
request processing. There are three configuration parameters that affect the current value of the
pending limit:
• *initial_pending_limit: the base value of the pending limit
• *max_pending_limit: the maximum value of the pending limit
• *limit_multiplier: current pending limit * limit_multiplier = new pending limit
• *pending_resize_trigger: the size of the pending list when the resize is applied
Initially, the pending limit is set to initial_pending_limit. At any one time, there can be at most
pending limit number of requests outstanding. If the number of requests outstanding hits the pending
limit, the pending limit will be raised to the value:
(current pending limit * limit_mulitplier)
when the last pending request is completed successfully. Then pending limit number of requests may
be made.
If any pending request fails (due to no response, for instance), the pending limit is reset to
initial_pending_limit. The pending limit will never exceed the value max_pending_limit.

SFC Developer’s Guide 284


5 SFC IMPLEMENTATION DETAILS

In light request traffic, the pending limit will remain at its current level and requests will go out as they
are received. When a large burst of requests causes the pending limit to be hit, the limit will be raised
and a new set of requests will be made upon the successful completion of the last pending request.
Normally the pending list is only resized when it is empty. However, if a few of the requests take a very
long time to receive images or inactive events, requests in the waiting list will not be sent, and image
throughput will suffer. If pending_resize_trigger is set to be > 0, the slow items will not prevent the
queue from resizing and additional requests from being made. When the pending list reduces to the
size of the resize trigger, the queue resize algorithm described above will be used.

5.4.4.2 Request Timing


In the SFC, the request item implementation will make its own requests for data via the SSL and will
interact with the request queue. When requests fail, the item will attempt to retry the request.
There are four configuration parameters associated with timing requests and timing request retries:
• *timeout_seconds: time to wait for a response to a request
• *retry_seconds: initial amount of time to wait before a request retry is attempted
• *retry_cap_seconds: maximum amount of time to wait before a request is retried
• *retry_multiplier: current retry time * retry_multiplier = new retry time
Upon making a request, the item will be pending in the request queue. The request item schedules its
data request and will eventually take itself out of the pending queue if a response is not received within
timeout_seconds.
Upon timing out or receiving a data response that indicates the data cannot be accessed at the
moment, an item will wait retry time (seconds) before re-requesting. Initially, the retry time is set to
retry_seconds. If the next request attempt fails, the retry time is set to (current retry time *
retry_multiplier). This continues until the request is successfully completed or the item becomes
inactive. The maximum value of the retry time is retry_cap_seconds.

5.4.4.3 Configuration
The following parameters can be set in the SFC configuration file:
*request_queue*initial_pending_limit : 10
*request_queue*max_pending_limit : 100
*request_queue*limit_multiplier : 2

SFC Developer’s Guide 285


5 SFC IMPLEMENTATION DETAILS

*request_queue*pending_resize_trigger : 0
*request_item_config*timeout_seconds : 100
*request_item_config*retry_seconds : 10
*request_item_config*retry_cap_seconds : 5000
*request_item_config*retry_multiplier : 3
All of the values shown above are the defaults.
This configuration assumes that the application creates an instance of RTRXFileDb and makes this
instance the global configuration database by calling RTRConfig::setConfigDb() and passing the
new RTRConfigDb instance.

NOTE: Make sure you include the "*" in front of the "request_queue" portion of the identifier. (See
section 4.8.5 for details.)

5.4.5 Image Publishing

5.4.5.1 Relationship between SFC and Source Distributor Cache Size


The SFC configuration variable *number_of_items controls the size and efficiency of SFC’s cache
and also may affect a 4.2 Source Distributor or later. The Source Distributor has a configuration
variable called *maxCache that sets the maximum hash table size for the Source Distributor’s cache
list and a configuration variable called openLimit (which can be set on a per service basis) that sets
the hash table size for the Source Distributor’s cache list. The Source Distributor will set its cache size
to the lesser of these two values.
The Source Distributor’s *cacheType configuration variable (sinkDriven or sourceDriven) and the
Source Distributor’s *preemptionLocation (none, SSL, srcApp) configuration variable specify how the
cache list should be managed.
• If the *cacheType is sinkDriven and the *preemptionLocation is none or SSL, the Source
Distributor controls the size of the cache list.
• If the *cacheType is sourceDriven or the preemptionLocation is srcApp, SFC controls the size
of the cache list. The *preemptionLocation parameter is only applicable to sinkDriven
applications.
When the Source Distributor controls the size of the cache list, it checks the maxCache whenever it
attempts to add an item to the cache list (and preempts an item if necessary and so configured).

SFC Developer’s Guide 286


5 SFC IMPLEMENTATION DETAILS

When the source application controls the size of the cache list and maxCache is configured as 0
(zero) or not present in the Source Distributor’s configuration file, the SFC source application’s
publisher service *number_of_items value will be used as the maximum cache size. If the Source
Distributor’s *maxCache is configured to greater than 0 (zero) in the Source Distributor’s configuration
file, the SFC source application’s publisher service’s *number_of_items value will be used as the
Source Distributor’s openLimit value. So, in this case the Source Distributor will set its cache size for
this service to the lesser of the Source Distributor’s maxCache and SFC’s *number_of_items.
More information is available in the Reuters Market Data Hub - Source Infrastructure 4.2 Software
Installation Manual.

5.4.5.2 Source-Driven Publishers


See Table 4.9 (Section 4.2.4) for more information on which implementations support sink and source-
driven publishing.

5.4.5.3 Image Pacing


If a publishing application preloads its cache, SFC will pace the publishing of images to the
infrastucture component. SASS2 and SASS3 local publishers will automatically take advantage of this
feature to reduce the flood of images to the network and normallize CPU usage on the application’s
host. On an RMDS Market Data Hub and a Triarch infrastructure, source-driven publishers have the
ability to preload the cache of a 4.2 or later Source Distributor in the similar manner. This can improve
performance by decreasing publisher to subscriber latency and reducing request traffic between the
Source Distributor and the publishing application.
While an RTIC will not need to be configured to take advantage of image pacing, a Source Distributor
will need the following configuration parameters set in the Source Distributor’s triarch.cnf file (see
Source Distributor documentation for full details):
<servicename>*cachelocation: ssl
<servicename>*cachetype: sourceDriven
There are two infrastructure independent configuration parameters available to the SFC source
application user that allow for configuration of some behavioral aspects of image pacing. The following
parameters can be set in the source application’s configuration file:
*imagesPerInterval : 30 ! default
*imageInterval: 100 ! default; in milliseconds

SFC Developer’s Guide 287


5 SFC IMPLEMENTATION DETAILS

When the source application completes a connection to an infrastucture component, the source
application will issue the images for all of the items in a service over a period of time. This set of
images is broken down into subsets (defined by *imagesPerInterval) and sent to the Source
Distributor at intervals (defined by *imageInterval) which would, by default, publish 300 images per
second. These parameters allow the user to avoid sending out a very large number of images in a very
short period of time, which could lead to overloading socket connection or Rendezvous daemon.
.
NOTE: In source-driven mode, a source application should pre-load its cache before a Source Dis-
tributor connects to it or it connects to an RV daemon. Otherwise, the pacing algorithm described
above will not be used. To pre-load SFC’s cache, create and populate all records before calling
RTRRTRecordServiceImpl.indicateSync().

When publishing to a Source Distributor it is important to have the Source Distributor configured to
handle a very large number of images.The Source Distributor also has a parameter called "open
window". This specifies the maximum number of outstanding image requests allowed at any given
time. Currently, the default is 40. The configuration variable to set the Source Distributor’s open
window is *initialOpenLimit. This is a configuration variable found in the triarch.cnf file. Please see
the Source Distributor’s documentation for more details.

5.4.5.4 Performance and Record Templates


SFC publishers have the ablility to add a new field during a Record resync event (see section 4.2.2.5
for details). There is a performace tradeoff however. Adding a field does not work if a record template
is used, but the infrastucture performace is slower if the infrastucture does not use record templates.

5.4.6 Tracing
SFC provides several mechanisms for tracing that can aid in troubleshooting the network configuration
and the application.
To turn on tracing, the debug filter must first be enabled in the selector configuration variable:
*selector : *.debug

5.4.6.1 RMDS/SSL Publishing and RMDS Subscription


In the configuration file, tracing can be enabled with:

SFC Developer’s Guide 288


5 SFC IMPLEMENTATION DETAILS

*traceLevel : <level>
which will begin logging debug messages to the logger. <level> is an integer bitmask used to set
various levels of tracing. Valid values are created by adding the integer values of each level that is to
be logged.
1= service level tracing
2 = basic item level tracing
4 = full item level tracing
8 = item image/update data tracing
In the TIB implementation, level 8 sends the full parsed TIBMsg to stderr.
The "debug" filter must also be enabled in the *selector configuration variable.
For example, to turn on service level and item image and update data tracing, the following entries
would be used:
*selector: *.debug
*traceLevel: 9

5.4.6.2 SSL Subscription


In the configuration file, SSL client-side tracing can be enabled with:
*item_debug : true
The "debug" filter must also be enabled in the *selector configuration variable.

5.4.7 Low-level Tracing and Error Messages


Protocol-level error messages are not sent to the SFC logging mechanism. Instead, they are output to
protocol-specific files.
SSL library error messages are sent to SSL.log. The name of the SSL log file can be set with SFC’s
*sslLogFile configuration variable. This file will include additional tracing of the sink mount parameter
if SFC’s *mountTrace configuration variable is set to True. The maximum size of the file can be set
with *sslLogFileSize.

SFC Developer’s Guide 289


5 SFC IMPLEMENTATION DETAILS

Additionally, IPC messages to Triarch and the Market Data Hub can be traced using the sslapi.cnf
configuration variables *eventLogging, *messageTracing, and *functionLogging, described in
section B.6.3. The IPCTRACE file created with this configuration is always in the local directory.
For RMDS, SASS3 library error messages are sent to SASS3.log. The name of the SASS3 log file can
be set with the *tiblogfile configuration variable.
The following configuration summarize these configuration variables with their defaults:
*sslLogFile : SSL.log
*sslLogFileSize : 10000
*mountTrace : False
*tiblogfile : SASS3.log

SFC Developer’s Guide 290


5 SFC IMPLEMENTATION DETAILS

5.5 Implementation Issues


This section discusses miscellaneous infrastructure details and compatibility issues. Throughout this
section, references to an RTIC assume a standard RMDS configuration, using Marketfeed and not
using tss_records.cf. For more details on how an RTIC behaves when configured with
tss_records.cf and tss_fields.cf, see Appendix E.

5.5.1 Cross-infrastructure Compatibility


The C++ Edition has made considerable effort to try to hide compatibility issues between
infrastructures. In most circumstances, the startup code in the main() routine selects an
implementation and the rest of the application is infrastructure independent. In some circumstances, it
does not hide those differences. The following table lists the potential issues and the sections that
discuss the issue in greater detail.

Issue Section

Entitlement system used section 5.3.1

Data format details section 5.5.2

Record template numbers section 5.5.3

Data dictionaries used section 5.5.4

Dynamic service availability section 5.5.6

Subjects for news headlines section 5.5.7.6

RIC to subject mapping section 5.5.7

Page attribute encoding section 5.5.8.2

Model to use for inserts section 5.5.9

Rendezvous 6 interoperability section 5.5.11

Rendezvous 5 interoperability section 5.5.12

Table 5.4: Cross-infrastructure Compatibility Index

SFC Developer’s Guide 291


5 SFC IMPLEMENTATION DETAILS

5.5.2 Data Format


SFC supports two data dictionary formats: Marketfeed data dictionary (appendix_a and
enumtype.def) and TSS data dictionary. The Marketfeed data dictionary is originated from Triarch
infrastructure and supported in Triarch and RMDS infrastructures. The TSS data dictionary is
originated from TIB infrastructure and currently supported only RMDS infrastructure.
The RMDS and Triarch market data infrastructures encode the same data in different ways regarding
the dictionary formats used. While SFC hides most of these differences, some of these differences
come through the interface. The two primary differences that an SFC developer will need to be
concerned with for cross-infrastructure compatibility are FIDs and record templates.
• The FIDs used in Marketfeed-based and in TSS-based are usually different. The field names,
however, are the same. For example, the FID for the field "BID" is 22 on Marketfeed-based, but it
could be 10720 on a TSS-based. To be safe, use RTRRTRecord::fieldByName(const char *)
when accessing fields in a record.
• Fields in TSS-based do not have long names (the DDE acronym column in Triarch’s and RMDS’s
appendix_a), so RTRField::longName() will just return the same value as RTRField::name().
• Custom field definitions added to the appendix_a are required to have a negative FID. TSS-
based does not have this restriction.
• In TSS-based, field names can contain whitespace. In Marketfeed-based, however, they cannot.
The simplest workaround is to replace the whitespaces with underscores on both infrastrucures. If
they are absolutely needed, then write your application to use RTRField::longName() and put
the full field name in the DDE acronym column of the appendix_a:
ACRONYM DDE ACRONYM FID RIPPLES TO FIELD TYPE LENGTH
------- ----------- --- ---------- ---------- ------
NEW_FIELD "NEW FIELD" -1 NULL ALPHANUMERIC 10

• Both dictionaries must at least know the FID definitions for all of the field names that will be
published. If SFC does not have a FID definition for a field, it will throw it out. If the infrastructure
cache does not have a FID definition for a field, it may also throw it out.
• The size of a price field is hardcoded to 17 bytes causing price fields which are larger than 17
bytes to be truncated. On Marketfeed-based this can be solved by modifying appendix_a. To
increase the size while using a TSS-based dictionary, SFC provides the configuration variable
*decimalSize to work around this issue. TSS-based format has an opaque data type that
supports binary data for a fixed size. SFC translates that type to RTRFidDefinition::Binary.

SFC Developer’s Guide 292


5 SFC IMPLEMENTATION DETAILS

However, the Marketfeed data format used by Triarch and RMDS is limited to a 182-character set.
Binary fields in the appendix_a are actually base64 encoded in Marketfeed; RTRField’s
setFromBinaryData() and binaryData() methods can be used to encode and decode binary data
for all infrastructures.
• Page data in the Triarch and RMDS infrastructures is delivered as a stream of ANSI data. While
SFC parses the ANSI data and makes it available in a logical model, sometimes status text
messages also have ANSI escape sequences in them. SFC does not parse these ANSI escape
sequences, so the text in processInfo events will still contain the sequences.
• When using TSS dictionary format, SFC now allows consumers access to the SEQ_NO FID.
Previously SFC dropped this field. If it is necessary to have SFC automatically drop this field, set
*dropSeqNo to True. *dropSeqNo is False by default and will only need to be changed in rare
cases.
• When publishing to an RTIC(SASS2) infrastructure, SFC automatically create fields for
"SYMBOL" and "Output Ticker Symbol". Those fields are populated with the RIC for the item. The
configuration parameter *sendSymbolFields allows the publisher to disable the publishing of
SYMBOL and Output Ticker Symbol fields. The default value for this configuration parameter is
true for publishing SYMBOL and Output Ticker Symbol.
• When publishing chain over RTIC(SASS3) infrastructure, SFC configuration variable
*enableNextChainHeaderAsString must be set to True; otherwise, the size of chain elements
on the subscriber side would not be changed.
*enableNextChainHeaderAsString = True
• On the SASS3 protocol, SFC publisher can be configured to encode the published data to MF
data format by setting the configuration variable *mfencoder to True.

5.5.2.1 Enumerations

Consumers
When using SFC with Marketfeed-based program, both enumerated and expanded values will be
available for all enumerated fields. If the datafeed is expanding the enumerated fields upstream, SFC
will not look up the enumerated value if the configuration variable srcExpandsEnumFields is set to
True. The srcExpandsEnumFields configuration variable can be set on a per service basis.

SFC Developer’s Guide 293


5 SFC IMPLEMENTATION DETAILS

TSS-based program expands all enumerations upstream and does not provide a way of looking up the
original enumerated value. No RTRRTEnumeratedFields will be created by the TIB implementation of
SFC. They will instead be of type RTRRTAlphanumericField.
For compatibility between the models, first check the type of the field. If it is enumerated, use
RTRRTEnumeratedField::expandedValue(). Otherwise use RTRField::string() to access the value.
// RTRRTRecord & record;

if (record.hasFieldByName("RDN_EXCHID")
{
RTRField *field = record.fieldByName("RDN_EXCHID");
if (field->type() == RTRFidDefinition::Enumerated)
cout << ((RTRRTEnumeratedField *)field)->expandedValue();
else
cout << field->string();
}

Publishers
Publishing enumerated fields presents some challenging tradeoffs. The issue centers around sending
data in the format (either enumerated or expanded) that the consuming program expects.
• If the publisher will only be used in a single infrastructure, then it can use the format expected in
that infrastructure.
• If the consumer is also an SFC-based program, then one of the consumer workarounds described
above can be used.
• If the publisher will be publishing to consuming applications that cannot be changed or
configured, then the publisher may need to add conditional code or configuration to change what
it publishes in the infrastructure in which it is deployed.
The following code shows how to conditionally publish an enumerated field as either Enumerated
or Alphanumeric:
// RTRRTRecordImpl & record;
// RTRFidDb & fidDb;

RTRFidDefinition * fidDef = fidDb.defByName("RDN_EXCHID");


if (fidDef)
{

SFC Developer’s Guide 294


5 SFC IMPLEMENTATION DETAILS

char * farea = new char[fidDef->length() + 1];


RTRRTField * fld;
if (fidDef->type() == RTRFidDefinition::Enumerated)
{
fld = new RTRRTEnumeratedField(*fidDef, farea, 0,
*fidDb.enumTableByName("RDN_EXCHID"));
fld->set("2", 1);
// Note that only the enumerated value is set. The consumer
// will be responsible for looking up the expanded value.
}
else // RDN_EXCHID is Alphanumeric in TIB infrastructure
{
fld = new RTRRTAlphanumericField(*fidDef, farea, 0);
fld->set("NYS", 3);
}
_record.putField(*fld);
}

The following table summarizes how enumerations are received for various infrastructures. In each
row, the RDN_EXCHID field is being published. The value sent by the publisher is what will be sent
through the infrastructure. The client values show what will be available through SFC. The f and ef
variables are RTRRTField and RTRRTEnumeratedField, respectively. The value returned by string()
is the value actually stored by SFC.

Infrastructure / Value sent by SFC consumer


Client values
FID definition type publisher configuration

RTIC Enumerated (2) Any f.string() = "2"


/ Alphanumeric
(works, but is not the value
typically expected from TIB)

RTIC Expanded (NYS) Any f.string() = "NYS"


/ Alphanumeric

Table 5.5: Enumeration Summary by Infrastructure

SFC Developer’s Guide 295


5 SFC IMPLEMENTATION DETAILS

Infrastructure / Value sent by SFC consumer


Client values
FID definition type publisher configuration

Triach & RMDS / Enumerated (2) Default ef.enumeratedValue() = 2


Enumerated ef.expandedValue() =
"NYS"
ef.string() = "2"

Triach & RMDS / Enumerated (2) *srcExpandsEnum- Invalid configuration


Enumerated Fields: true

Triach & RMDS / Expanded (NYS) Default ef.enumeratedValue() = 0


Enumerated ef.expandedValue() = ""
ef.string() = "2"

(only string() returns a valid


value)

Triach & RMDS / Expanded ( NYS) *srcExpandsEnums- ef.enumeratedValue() = 2


Enumerated Fields: true ef.expandedValue() =
"NYS"
ef.string() = "2"

Table 5.5: Enumeration Summary by Infrastructure (Continued)

5.5.2.2 Hint
SFC allows system to identify data display format by determining hint which can be grouped into 3
forms as described in table 5.6.

NOTE: Hint is only applicable to SFC consumer. There is no control for SFC publisher over hints, so
SFC will automatically generate appropriate hint for each field when it is published.

SFC Developer’s Guide 296


5 SFC IMPLEMENTATION DETAILS

Type of Data
Hint Examples Data Display
Displaying

Display in fraction form, TSS_HINT_DENOM_2 123.5 +123 1/2


divider specified by hint. TSS_HINT_DENOM_4 +123 2/4
TSS_HINT_DENOM_8 +123 4/8
TSS_HINT_DENOM_16 +123 8/16
TSS_HINT_DENOM_32 +123 16/32
TSS_HINT_DENOM_64 +123 32/64
TSS_HINT_DENOM_128 +123 64/128
TSS_HINT_DENOM_256 +123 128/256

Display in floating point TSS_HINT_DECIMAL_1 12.3456789 +12.3


form by specified decimal TSS_HINT_DECIMAL_2 +12.35
part digits. TSS_HINT_DECIMAL_3 +12.346
TSS_HINT_DECIMAL_4 +12.3457
TSS_HINT_DECIMAL_5 +12.34568
TSS_HINT_DECIMAL_6 +12.345679
TSS_HINT_DECIMAL_7 +12.3456789
TSS_HINT_DECIMAL_8 +12.34567890
TSS_HINT_DECIMAL_9 +12.345678900

Display in original form. TSS_HINT_DENOM_NONE 123.45 +123.45


TSS_HINT_32_PLUS
and other types.

Table 5.6: Data Displaying


The data buffer size can be set by configuring the configuration variable *decimalSize of which the
default value is 17. However, this buffer size must be reserved at least two digits for a sign string and a
string termination. This configuration variable is applicable only with TSS data dictionary. See section
5.5.2 for purposes of this configuration variable.
SFC will display data in several ways, depending on a hint that comes with the data. The hint will
determine displaying data format under several scenarios as described below. The buffer size used in
the examples are 17.

SFC Developer’s Guide 297


5 SFC IMPLEMENTATION DETAILS

Scenario 1. SFC will strictly follow the hint if the data buffer size is sufficient.

Data Hint Display

123 TSS_HINT_DENOM_NONE +123

123 TSS_HINT_DECIMAL_9 +123.000000000

123.456 TSS_HINT_DENOM_NONE +123.456

123.456 TSS_HINT_DECIMAL_9 +123.456000000

123.4567 TSS_HINT_DECIMAL_3 +123.457

Table 5.7: Example of SFC Displaying Data Using Hint

Scenario 2. SFC will display data as hint, but the decimal part may be rounded up or rounded
down depending on the available buffer size.

Data Hint Display

123456789 TSS_HINT_DECIMAL_9 +123456789.00000

12345678.90123 TSS_HINT_DECIMAL_8 +12345678.901230

1234567 TSS_HINT_DECIMAL_9 +1234567.0000000

1234567890123 TSS_HINT_DECIMAL_9 +1234567890123.0

12345678901234 TSS_HINT_DECIMAL_9 +12345678901234

123456789012345.678 TSS_HINT_DENOM_NONE +123456789012346

Table 5.8: Example of SFC Displaying Data by Truncating Decimal

SFC Developer’s Guide 298


5 SFC IMPLEMENTATION DETAILS

Scenario 3. SFC will display data in exponential form without hint associated when the buffer
size is not sufficient for a whole number. This causes the data to be rounded up or rounded
down in some cases.

Data Hint Display

1000000000000000 TSS_HINT_DENOM_NONE +1e+015

1000000000000000 TSS_HINT_DECIMAL_9 +1e+015

1234567890123456789 TSS_HINT_DENOM_NONE +1.23456789e+018

1234567890123456789 TSS_HINT_DECIMAL_9 +1.23456789e+018

1234567890123456.789 TSS_HINT_DENOM_NONE +1.23456789e+015

1234567890123456.789 TSS_HINT_DECIMAL_9 +1.23456789e+015

123456789987654321012 TSS_HINT_DENOM_NONE +1.2345679e+020

Table 5.9: Example of SFC Displaying Data in Exponential Form


A log message will be generated when:
1. Data could not be displayed as hint. Displaying data as hint requires a larger buffer size than
an allocated buffer size does. Message will be printed as "could not be displayed as hint.".
2. Truncation validation. Truncation process can be ceiling and floor. The validation will be
performed in the following cases:
• Hint is defined as TSS_HINT_DENOM_NONE or TSS_HINT_32_PLUS.
• Data could not be displayed as hint. Truncation validation will be validated in scenario 1 as
well.
Upon truncation validation event, message will be printed only when the data is rounded up or rounded
down. Message will be printed as "it is rounded up." or "it is rounded down.". The severity level of log
message is "warning".

SFC Developer’s Guide 299


5 SFC IMPLEMENTATION DETAILS

5.5.3 Record Templates


Record templates provide a list of all of the fields in a particular record. The record template number is
sometimes referred to as the field list number. In TSS-based dictionary format the record templates are
defined in tss_records.cf and its supporting fields. In IDN, record templates are specified in a file
commonly known as "Appendix D." "Field templates" is another name for the data dictionary or FID
database, described in section 5.5.4.
The record templates in TSS and Marketfeed data dictionary formats may be different. This is usually
not a concern because the key fields of interest are available on both infrastructures. However, this
can be an issue when writing gateway applications between Triarch and RTIC/TSS or RTIC/TSS and
RMDS.
RTRString * RTRRTRecord::recordTemplateNumber() provides access to the field list number from
the Marketfeed header or the REC_TYPE field from a Rendezvous message. If these values are not
set, this method will return a null pointer.
RTRRTRecordImpl::setRecordTemplateNumber( RTRString * ) is used by publishing applications
to set the string of the record template number for a single record. This method is part of the
RTRRTRecordImpl abstract interface and is applicable in TIB and SSL implementations. In the SSL
implementation of SFC, this method uses the value to set the field list number that is published in the
Marketfeed message header. In the TIB implementation this method sets the value that will be put in
the REC_TYPE field of the published message.
While the methods for getting and setting the record template number are generic for SSL and TIB
implementations, there are several infrastructure issues to consider:
• If the record template number is not available, a NULL pointer will be returned by
recordTemplateNumber().
• Record templates are a legacy concept on Triarch. Very few components actually use them.
• For TSS the record template number must match a template in tss_records.cf and its supporting
files. Otherwise it might not be cached.
• When a record template number is published, the RTIC will cache exactly the fields defined for
the record template number. If fields are missing from the image, the TIC will populate those fields
with empty values. If the publisher sends extra fields not in the template, the RTIC will throw them
out.

SFC Developer’s Guide 300


5 SFC IMPLEMENTATION DETAILS

• When record templates are used, the RTIC will never add or remove fields, even if another image
is published. When record templates are not used, the RTIC will replace the item in the cache
when a TIB_MSG_VERIFY (i.e. record resync) is received.
• REC_TYPE is required when using the record publishing model to send contributions on a
Rendezvous network.
• Record template numbers have different values on TSS and Marketfeed data dictionaries. Since
most Marketfeed data dictionary do not use fixed record templates, the TSS data dictionary
values can be used.
Due to these issues, SFC’s TIB implementation has an additional mechanism for controlling when
record template numbers are published. First, the generic record publishing code can be written to
always publish record template numbers. Then record template number publishing can be controlled
for a service either programmatically or through configuration.
RTRRTFieldToTIBRecordService::setUseTemplates();
RTRRTFieldToTIBRecordService::clrUseTemplates();
setUseTemplates() enables publishing of the REC_TYPE field, and clrUseTemplates() disables
publishing of that field, regardless of whether the setRecordTemplateNumber() method was used. If
the template behavior is not set programmatically, the *useTemplates configuration variable can be
used. That configuration variable defaults to true. Setting *useTemplates to false is equivalent to
calling clrUseTemplates().

NOTE: If the record template number is only being used to distinguish between different types of
records and is not being used to define an exact set of fields for a record template, then the
RDNDISPLAY field can probably be used. This field is typically used to select a display template,
and it is available from all infrastructures.

5.5.4 Data Dictionary


Data dictionary is a term that is often used for field templates or FID database. SFC uses the abstract
class RTRFidDb for data dictionaries. Two key implementations of this interface are RTRSSLFidDb
and RTRTIBFidDb. See the SFC Reference Manual for information on these classes.
Triarch and RMDS use the Marketfeed data dictionary that is specified in the appendix_a and
enumtype.def files. The RMDS infrastructure also supports downloading of data dictionary files from
the P2PS or RTIC, with a few limitations. Moreover, RMDS(RTIC) also supports the TSS data

SFC Developer’s Guide 301


5 SFC IMPLEMENTATION DETAILS

dictionary that is loaded from tss_fields.cf, tss_records.cf, and supporting files. Many data
discrepancies between infrastructures can be linked to data dictionary differences.

5.5.4.1 Sharing a Data Dictionary


If the data dictionary is not explicitly created and passed to the service in the constructor, SFC will
create the correct type of data dictionary. The service pool factory classes also create the correct type
of data dictionary.
The application has the option of creating the data dictionary directly and passing it to the service in
the constructor. This is typically done for one of the following reasons:
• to share a data dictionary between a publishing and subscribing service
• to share a data dictionary between two subscribing services that have two different connections.
Note that a service pool factory can be used to share the FidDb between services on the same
connection.
• to pass a data dictionary that was downloaded from one Rendezvous session to a publishing
service on a different session. This is necessary when the TIC or RTIC’s configuration file has
different values for RV3_PUBLISH_SERVICE, RV3_PUBLISH_NETWORK, and
RV3_PUBLISH_DAEMON than it does for RV3_OUTPUT_SERVICE,
RV3_OUTPUT_NETWORK, and RV3_OUTPUT_DAEMON.
The application also has three options to handle the data dictionary classes:
1. RTRSSLFidDb::load() can be used to load the data dictionary from file or download from the
network (P2PS) for RMDS.
2. RTRFileFidDb::load() can be used to load the data dictionary from the local appendix_a and
enumtype.def files for Triarch and RMDS.
3. RTRTIBFidDb::load(FidDbType = Marketfeed, FidDbLocation = Default) can be used to load
the data dictionary from file or download from the network for RMDS.
The *fidDbType configuration variable can be used to override the type of data dictionary used for a
service. If the variable is set to "Marketfeed", the dictionary will be based on an appendix_a and
enumtype.def and the default location will be files. If the variable is set to "TSS", the dictionary will be
based on a tss_fields.cf and the default location will be the network.
The FID database location can also be controlled through the *fidDbLocation configuration variable. If
the variable is set to "file", the data dictionary will be loaded from files. If the variable is set to

SFC Developer’s Guide 302


5 SFC IMPLEMENTATION DETAILS

"network", then the data dictionary will be downloaded from the P2PS or RTIC. See Appendix C.2.3
and Appendix E.4 for information on how to configure the infrastructure to support data dictionary
download. If the *fidDbLocation variable is not set, the default location for that type of data dictionary
will be used. For TSS, the default location is network. For Marketfeed, the default location is file.
When the *fidDbLocation is "file" for a TSS data dictionary, the fid_file_path configuration variable
must be set to the fully qualified filename of tss_fields.cf . Also, the cfile_path environment variable
must include the directory in which tss_fields.cf and its support files are found. The fid_file_path
config variable and the cfile_path environment variable should be set using forward slashes (e.g.
cfile_path = /var/tib; *fid_file_path: /var/tib/tss_fields.cf).
If the data dictionary is loaded from files, the *fid_file_path and *enum_file_path configuration
variables can be used to set the location. The priority for determining the data dictionary location is as
follows:
1. filenames passed in constructor or load() methods
2. filenames found in *fid_file_path and *enum_file_path
3. the current working directory
4. \\HKEY_LOCAL_MACHINE\SOFTWARE\Reuters\Triarch\MASTER_FID_FILE and
\\HKEY_LOCAL_MACHINE\SOFTWARE\REuters\Triarch\ENUM_FILE
registry entries (Win32 only)
5. MASTER_FID_FILE and ENUM_FILE environment variables
In order to load both tss_fields.cf and appendix_a from files specified in configuration, configuration
class IDs should be used. For example:
*fidDbLocation: file
FileFidDB.fid_file_path: /var/triarch/appendix_a
FileFidDB.enum_file_path: /var/triarch/enumtype.def
TIBFidDB.fid_file_path: /var/tib/tss_fields.cf

5.5.4.2 Infrastructure Issues


RTRSSLFidDb and RTRFileFidDb should always be used with the SFC’s SSL implementation. A
RTRTIBFidDb should always be used with SFC’s TIB implementation. Using a RTRFileFidDb with the
RMDS infrastructure may prevent data from being parsed correctly.
While the SFC model supports a separate RTRFidDb for each service, the TIBMsg parser used for
RMDS and TIB market data uses two global data dictionaries. One of these data dictionaries is TSS-

SFC Developer’s Guide 303


5 SFC IMPLEMENTATION DETAILS

based and the other is Marketfeed-based. When a RTRTIBFidDb is loaded, one of the two global data
dictionaries is loaded. If another RTRTIBFidDb of the same type is loaded, the data dictionary in the
parser is replaced, and services based on the first data dictionary will begin to use the second for
parsing.

RMDS/RTIC/
RMDS/RTIC/
Triarch RMDS/P2PS Marketfeed
TSS based
based

Class Name RTRSSLFidDb, RTRTIBFidDb RTRSSLFidDb, RTRTIBFidDb


RTRFileFidDb RTRFileFidDb

Type Marketfeed TSS Marketfeed Marketfeed

Possible Loca- file network, file network, file network, file


tions

Default Location file network file file

Default File- appendix_a, tss_fields.cf appendix_a, appendix_a,


name(s) enumtype.def enumtype.def enumtype.def

Enumerations yes no yes yes

Table 5.10: Data Dictionary Summary by Infrastructure

5.5.4.3 Examples
The examples in this section show how to use the RTRTIBFidDb::load() methods and service
constructors to share data dictionaries. The examples may use some of the following includes and
declarations:
#include "rtr/objid.h" // RTRObjectId
#include "rtr/tibrtsvc.h" // RTRTIBRTRecordService
#include "rtr/tfdb.h" // RTRTIBFidDb
#include "rtr/tconnect.h" // RTRTIBConnection
#include "rtr/fldtossl.h" // RTRRTFieldToSSLRecordService
#include "rtr/fldtotib.h" // RTRRTFieldToTIBRecordService
RTRObjectId appId("appId");
RTRRTRecordService * subservice;

SFC Developer’s Guide 304


5 SFC IMPLEMENTATION DETAILS

RTRRTRecordServiceImpl * pubservice;
RTRTIBConnection * c;
RTRTIBFidDb * fidDb;
1. RMDS local publishing and subscribing services, Marketfeed-based data dictionary from file
c = new RTRTIBConnection(appId, "connection");
c->connect();
fidDb = new RTRTIBFidDb(appId, c);
fidDb->load(); // Marketfeed, File is default
subservice = new RTRTIBRTRecordService(appId, "IDN", *fidDb, *c);
pubservice =new RTRRTFieldToTIBRecordService(appId, "PUB", *fidDb, *c);
2. RMDS local publishing and subscribing services, Marketfeed-based data dictionary from
network
connection = new RTRTIBConnection(appId, "connection");
c->connect();
fidDb = new RTRTIBFidDb(appId, c);
fidDb->load(RTRTIBFidDb::Marketfeed, RTRTIBFidDb::Network);
subservice = new RTRTIBRTRecordService(appId, "IDN", *fidDb, *c);
pubservice =new RTRRTFieldToTIBRecordService(appId, "PUB", *fidDb, *c);
3. RMDS local publishing and subscribing services, TSS-based data dictionary from file
c = new RTRTIBConnection(appId, "connection");
c->protocol(RTRTIBConnection::SASS2); //SASS3 is also valid if
//using a RTIC(SASS3)
fidDb = new RTRTIBFidDb(appId, c);
fidDb->load(RTRTIBFidDb::TSS, RTRTIBFidDb::File);
subservice = new RTRTIBRTRecordService(appId, "RSF", *fidDb, *c);
pubservice = new RTRRTFieldToTIBRecordService(appId, "PUB", *fidDb, *c);
4. RMDS local publishing and subscribing services, TSS-based data dictionary from network
c = new RTRTIBConnection(appId, "connection");
c->protocol(RTRTIBConnection::SASS2); //SASS3 is also valid if
//using a RTIC(SASS3)
fidDb = new RTRTIBFidDb(appId, c);
fidDb->load(RTRTIBFidDb::TSS); // Network is default for TSS
subservice = new RTRTIBRTRecordService(appId, "RSF", *fidDb, *c);
pubservice = new RTRRTFieldToTIBRecordService(appId, "PUB", *fidDb, *c);
5. Sharing data dictionary between a RMDS service and Triarch service.

SFC Developer’s Guide 305


5 SFC IMPLEMENTATION DETAILS

Note that the FidDb is loaded from a file. Also note that a RTRTIBFidDb is used, not a
RTRFileFidDb. This necessary because RTRTIBFidDb has the side-effect of correctly
initializing the RMDS parser.
c = new RTRTIBConnection(appId, "connection");
c->connect();
fidDb = new RTRTIBFidDb(appId, c);
fidDb->load(); // Marketfeed, File is default
subservice = new RTRTIBRTRecordService(appId, "IDN", *fidDb, *c);
pubservice =new RTRRTFieldToSSLRecordService(appId, "PUB", *fidDb, *c);
6. Downloading a data dictionary when the RTIC’s RV3_OUTPUT_* and RV3_PUBLISH_*
parameters or the RTIC’s RV2_OUTPUT_* and RV2_PUBLISH_* parameters are set.
const char * outservice = "7501";
const char * pubservice = "7502";
c = new RTRTIBConnection(appId, "connection", outservice,"","");
c->connect();
fidDb = new RTRTIBFidDb(appId, c);
fidDb->load(RTRTIBFidDb::TSS); // Network is default for TSS
pubservice =
new RTRRTFieldToTIBRecordService(appId, "PUB", *fidDb, pubservice,"","");
Note that for this setup, the SFC configuration file must have the following entry:
TIBDistribution*pingInterval : 0
or
TIBDistribution*enablePingSubscription : false

5.5.4.4 Configuration
*fid_file_path - Default location of appendix_a. This configuration variable is also used for loading
tss_fields.cf from a local file. To set both appendix_a and tss_fields.cf filenames through
configuration, FileFidDB and TIBFidDb Class IDs must be used. When loading tss_fields.cf, the
cfile_path environment variable must also be set to include the directory with the supporting .cf files.
See section 5.5.4.1 for details.
*enum_file_path - Default location of enumtype.def.
*fidDbInterval - If downloaded RTRSSLFidDb or RTRTIBFidDb did not load within this time period (in
seconds), it will be retried. The default value is 20.

SFC Developer’s Guide 306


5 SFC IMPLEMENTATION DETAILS

*fidDbLocation - Has no default. Can be set to "network" or "file" for RTRSSLFidDb or RTRTIBFidDb.
If it is not set, the default value for that infrastructure will be used.
*fidDbType - Has no default. Can be set to "Marketfeed" or "TSS" for RTRTIBFidDb. If it is not set, the
default value for that infrastructure will be used.

5.5.5 Data and Connection Status


All SFC applications can monitor the status of items and services by implementing the appropriate
record client, page client, service client, and connection client interfaces. Stale notifications are usually
received through a processStale event. Recovery conditions are received through itemResync,
itemNotStale, serviceSync, or connectionConnected events. When SFC logging is enabled, the log file
may also show some status events.
In the RMDS infrastructure, status information is primarily at the item level. Services are considered up
as long as the connection is up and the data dictionary is complete.

5.5.5.1 Data Status with RTIC


In SASS3 infrastructures, the RTIC has a mechanism for detecting when broadcast publishers die.
They expect a message from the publisher every so often. If no message is received within the timeout
interval, all items from that publisher are marked stale and stale events are broadcast for all
subscribers. For this mechanism to work:
• the RTIC must be version 10.1 or later.
• the RTIC must be configured. See Appendix D.4 and Appendix E.4 for details on configuring the
RTIC.
• the SFC local publisher must be configured with a unique numerical ID using the *groupId
configuration variable. The groupId can be configured on a per service basis. It is recommended
to configure the groupId to be > 1000 to avoid conflict with MDH services.
• the SFC local publisher’s *pingInterval must be less than FEED_FAIL_TIMEOUT configured in
the RTIC.
When RMDS consumers request non-cached items from a broadcast service and the infrastructure
component has BCAST_NAK set to true, the item will be marked as stale. Applications will receive
stale or info events, and the request will be periodically retried by SFC. In previous versions of SFC,
the item would be marked as inactive. To maintain this previous behavior, set the
*notFoundAsRecoverable configuration variable to false.

SFC Developer’s Guide 307


5 SFC IMPLEMENTATION DETAILS

When sourcing data from an RMDS service (SASS2/SASS3), an item that is in a stale state will
transition to a not stale state when an update which record status equals to OK is received and the
configuration variable *allowUpdatesToChangeStaleToOk is set to true. On the other hand, an item
that is in a not stale state will transition to a stale state when an update which record status equals to
STALE_VALUE is received.

5.5.5.2 Rendezvous Advisory Messages


The RMDS infrastructure can also receive status information through Rendezvous advisory
messages. Rendezvous advisory messages include RVD connection information such as
disconnections, license expiration warnings, and RVD overflows. The overflows could occur because
the subscriber client is too slow or a publisher on the network is too fast. This information is sent to
SFC applications through events on the RTRMDConnectionClient interface.
The _RV.WARN.SYSTEM.EVENTLOOP.STARVATION advisory indicates that the application is not
releasing the thread of control fast enough in callback functions. This event can occur if an application
is temporarily suspended or is too slow.
The _RV.ERROR.SYSTEM.CLIENT.SLOWCONSUMER advisory indicates that the application is too
slow. When this is received, the connection will be closed, making all market data services and items
stale. The connection will be re-established after waiting for 20 seconds. The reconnect delay can be
changed using the *slowconsumer_interval configuration variable. If the reconnect interval is less
than or equal to zero, the connection will not be terminated. After the connection recovers, the Items
will automatically be re-requested. See section 5.4.4 for information on when items will be re-
requested. If this advisory is frequently logged, the application should request less data or should be
run on a faster machine.
The _RV.ERROR.SYSTEM.CLIENT.FASTPRODUCER advisory indicates that the application is
publishing too fast. This is a warning message only, although a fast producer may lead to a
_RV.ERROR.RV.DATALOSS.OUTBOUND.
The _RV.ERROR.SYSTEM.CLIENT.NOMEMORY indicates that the application ran out of memory.
This could result in serious errors and could potentially crash the application. SFC will close the
connection, but will not try to reconnect because the state of the application could be corrupt. If this
event is received, the application should request less data or should be run on a machine with more
memory.
The _RV.ERROR.SYSTEM.LICENSE.EXPIRE indicates the RVD’s license has expired. SFC will close
the connection, but will not try to reconnect. The application should be restarted when the RVD has
been restarted with a new license.

SFC Developer’s Guide 308


5 SFC IMPLEMENTATION DETAILS

_RV.ERROR.RV.DATALOSS.INBOUND advisories indicate packets have been lost and cannot be


recovered. In this case, it is not possible to determine the effect of the loss, so SFC logs this
information and initiates a disconnect event and reconnect after a specified time interval. The time
interval is specified through configuration of *dataLossInboundInterval. The default for this interval is
0. A time interval of less than or equal to 0 disables the disconnect and reconnect functionality.
_RV.ERROR.RV.DATALOSS.OUTBOUND advisories indicate packets have been lost and cannot be
recovered. In this case, it is not possible to determine the effect of the loss, so SFC logs this
information and initiates a disconnect event and reconnect after a specified time interval. The time
interval is specified through configuration of *dataLossOutboundInterval. The default for this interval
is 0. A time interval of less than or equal to 0 disables the disconnect and reconnect functionality.

5.5.5.3 SSL Warning Messages


In the SSL log file (see section 5.4.7), warning messages may occur if the publisher is sending data
too quickly.
A message similar to:
file = src/ssl/edapi.c, line = 7802, Channel = 1
send_it: No Resources: Event Posting failed for Event 45.
or
ssl_errno = 10 on channel = 1
<src/ipc/sipcsrvr.c:3206> sipc46DataBuffer() failed, the output buffer may need
to be flushed
sipc_errno = 4 sys_errno = 0
file = src/ssl/edutils.c, line = 4082, Channel = 1
ssl_GetMsgBuffer: No Resources: Failed Getting Buffer for Channel 1.
indicates that sending the data failed and that data may have been lost. The application can increase
the number of output buffers used by changing the sslapi.cnf configuration variable
*numOutputBuffers. Increasing the value from the default uses more memory. See Appendix
B.6.3.16 for details on the configuration variable. For best performance results thorough load testing is
encouraged.

5.5.5.4 Status Event Normalization


In the TIB implementation, SASS3, and SASS2 status messages are normalized to the SFC market
data event model (Sync, Resync, Stale, Inactive, etc.). A variety of SASS messages are mapped to

SFC Developer’s Guide 309


5 SFC IMPLEMENTATION DETAILS

stale events. These events fall into two categories: those that SFC will try to recovery (for example
CACHE_FULL) and those that SFC will let the infrastructure recover (for example TMF_DOWN).
In most circumstances, SFC’s default mapping behavior is acceptable. In some environments, the
event mapping needs to be changed. The following configuration can be used to make some large
grain changes to how status codes fall into those categories:
*forceSFCDrivenRecovery : False
*forceInfrastructureDrivenRecovery : False
When *forceSFCDrivenRecovery is set to True, SFC will close all stale items and will re-request the
items. While this could speed up recovery in some circumstances, it could also lead to network request
"storms" if hundreds of applications are configured this way. In case RTIC is down, SFC will wait until
RTIC is up and then re-request the items.
When *forceInfrastructureDrivenRecovery is set to True, SFC will not re-request any stale items.
This can alleviate the network request load in complete system recovery situations. However, in some
circumstances, the items may never recover. This is especially true in the case of the SASS2 protocol.
If these configuration variables need to be set, then typically only one of them is set. These
configuration variables do not affect connection recovery or request queue timeouts.

5.5.6 Discovery

5.5.6.1 Service Pool Factory


On Triarch, services can be dynamically discovered, so the RTRSSLServicePoolFactory automatically
populates pools with services that are requested from it. The RTIC(SASS2) infrastructure does not
have a mechanism for broadcasting the names and types of all available services, so services must be
added to the RTRTIBServicePoolFactory manually or through configuration. With the SASS3 protocol
(RMDS infrastructure) services are dynamically discovered and automatically populate
RTRTIBServicePoolFactory.The dynamic behavior of the SSL and RMDS implementations can be
stopped (so it more closely mimics the RTIC(SASS2) implementation) by setting the following
configuration variables:
*enableDynamicRTRecordServices: false
*enableDynamicPageServices: false
*enableDynamicRTPageServices: false
*enableDynamicTimeSeriesServices: false
*enableDynamicInsertServices: false

SFC Developer’s Guide 310


5 SFC IMPLEMENTATION DETAILS

5.5.6.2 Service Provider Discovery


A special subject (<SERVICENAME>.QUERY.SERVICE.STATUS) is used by the SASS3 protocol
implementation to dynamically determine whether a service to publish to or consume from is an
RTIC(SASS3). It is also used to distinguish page and record services and to determine the default
sector used by the RTIC. In some environments, this mechanism will fail. In particular, the mechanism
will not work with:
• DTIC for RMDS (RDTIC)
• SSL Adapter-based programs using RTIC local publishing (sslrv.cnf configuration setting
*rticInsertMode: Publish)
• some RTIC configurations that filter out the QUERY "sector" or the STATUS "exchange."
In these circumstances, the mechanism must be disabled with the following configuration:
*<SERVICENAME>*serviceProvider : RTIC ! could also be TIC
"RTIC" would be used for an RTIC(SASS3) and an RDTIC. "TIC" should be used for an RTIC(SASS2).
When the provider discovery mechanism has been disabled, all services dynamically discovered
through the SASS3 protocol will be assumed to be record services. Also, setting *serviceProvider to
RTIC will make the default sector for subjects be "ANY" and setting *serviceProvider to TIC will make
the default sector for subjects be "REC". To override the default values for "Record" and "ANY" or
"REC, the following configuration can optionally be used:
*<SERVICENAME>*dataType : Record ! set to "Page" for page services
*<SERVICENAME>*defaultSector : ANY !! set to *sectorName from rtic.cf
! or set to the SECTOR from the tic.cf
If dataType is not set for page services, they will be assumed to be record services.
When the service provider discovery is used (*serviceProvider is not set), SFC will periodically retry
the QUERY subject until a response is received. The following configuration can be used to configure
how long SFC will wait before retrying:
*serviceStatusInterval : 15

SFC Developer’s Guide 311


5 SFC IMPLEMENTATION DETAILS

The *serviceProvider configuration variable controls the defaults of several other configuration
variables. The following table shows the relationship between various configuration variables.

*serviceProvider or
dynamic discovery Equivalent configuration Other values controlled
value

RTIC *defaultSector: ANY Page previous char: -


*sectorList: ANY Page next char: +
*fidDbLocation: file DACS Locks generated: no
*fidDbType: Marketfeed Renamable pages as snapshots: no
*newsEnabled: false Page parser: ANSI

TIC *defaultSector: DFLT Page previous char: p


*sectorList: REC, PAGE, Page next char: n
LINK DACS locks genereated: yes
*fidDbLocation: network Renamable pages as snapshots: yes
*fidDbType: TSS Page parser: TIBMsg
*newsEnabled: true

Table 5.11: Configuration relationships

5.5.7 Market Data Item Names and TIB Subject Names


Reuters Instrument Codes (RICs) are used for "symbol()" of SFC market data item names. For more
information on RICs, see the Selectfeed Plus User Guide.
The TIB implementation of SFC automatically maps RICs into four-part Rendezvous subject names.
The same mapping algorithm is used in the SSL Adapter. Most SFC applications do not need to be
concerned with the four-part names. However if SFC applications will interact with non-SFC
applications over the Rendezvous network, it is helpful to know how SFC uses the four-part naming
scheme. These names take the format:
<serviceName>.<sector>.<itemSymbol>.<exchange>

<serviceName> the name of the service (in SFC)


<sector> REC, LINK, PAGE, BRCAST, INTERACTIVE, or ANY

SFC Developer’s Guide 312


5 SFC IMPLEMENTATION DETAILS

<itemSymbol> base part of the symbol name


<exchange> suffix of the symbol name

The first, third and fourth parts of the name can be determined from the SFC service name and the
market data item name. The sector, however, must be guessed. On the client side, SFC takes its best
guess (based on the service type and the RIC). If that guess does not work, it cycles through the other
sectors. Table 5.12 shows some examples of the four-part names that SFC creates from the service
names and RICs.

Service name RIC Rendezvous name

RSF IBM.N RSF.REC.IBM.N

RSF IBM RSF.REC.IBM.NaE

RSF 0#.DJI RSF.LINK.0#^DJI.NaE

RDF .DJI RDF.REC.^DJI.NaE

RSF .AV.O RSF.LINK.^AV.O

RDF 1#.AV.O RDF.LINK.1#^AV.O

TELERATE 12 TELERATE.PAGE.12.NaE

RSF WRLD RSF.PAGE.WRLD.NaE

RSF NEWS2K_HL RSF.BRCAST.NEWS2K_HL.NaE

Table 5.12: Mapping SSL RICs to Rendezvous 4-part Subject Names

Sector selection is slightly different with an RMDS infrastructure. When a consuming SFC application
accesses data provided by the Market Data Hub through an RTIC, it will always use the sector from
service provider discovery (see section 5.5.6.2), which is typically "ANY". SFC local publishers,
publishing on the Rendezvous portion of an RTIC SASS3 infrastructure, will always use the "ANY"
sector by default. In RTIC/SASS2 infrastructure, it will always guess which sector should be used for
the publishing symbol. The sector can possibly be "REC", "LINK", "PAGE" and "BRCAST" which
depends on the publishing symbol.

SFC Developer’s Guide 313


5 SFC IMPLEMENTATION DETAILS

5.5.7.1 RIC to Subject Mapping


The SFC interface is standardized on the Reuters Instrument Code (RIC) naming scheme which
combines the <instrument> name and <exchange> into a single "symbol” and uses other special
character combinations to define special instruments like chains. For example, instrument "IBM” from
the NYSE exchange is published with a symbol name of "IBM.N”. The base record for the chain of
records that provide the volume leaders on the NASDAQ exchange is ".AV.O”. The instrument "IBM"
which is not from any exchange (i.e. <exchange> is "NaE") is published simply as "IBM."
Furthermore, the <serviceName> is determined by the service to which a record "belongs".
In order to properly map the SFC symbol name and serviceName into a valid 4-part subject name, the
TIB publishing service implementation will parse out the <exchange> from the record’s symbol name
and will apply a mapping algorithm to determine the <sector> for the given <instrumentName> and
<exchange>. This algorithm is encapsulated in the default implementation of the RTRTIBCustomizer
class.

SFC Developer’s Guide 314


5 SFC IMPLEMENTATION DETAILS

Determine the Use the next


Is this the first No
Sector sector in list
try?

Yes
No

1st char is
'n' or 't'?
1st char is 'd'?
Yes sector = REC
Yes
No
sector = PAGE
item
contains '#'?

Yes sector = LINK


No

item ends Done


with "X="? Yes sector = LINK

No

1st char '.' or all chars


'.' appears in Yes sector = LINK
before '.' are numeric?
item twice?

No

No
contains '/', but
not 1st char?

Yes sector = PAGE

No

item starts with sector =


Yes
"NEWS2K_"? BRCAST

No

item length > 4


Yes sector = PAGE
and alphanumeric?

No sector = REC

Figure 5.1: Sector Guessing

SFC Developer’s Guide 315


5 SFC IMPLEMENTATION DETAILS

5.5.7.2 Default Customizers

Default Record Subscription Customizer for RTIC/SASS2


The default record subscription customizer for RTIC/SASS2 uses an algorithm to guess the initial
sector. If this subject fails it will iterate through a list of additional guesses.
To change the list of guesses for sectors, *sectorList must be defined in the configuration file. This
configuration variable allows the client to set up a sequence of sectors (e.g. *sectorList: LINK, PAGE,
REC). SFC will use the sector names in the order specified in the sector list. News subject handling is
described in section 5.5.7.6.
This customizer can use subject map files for recording. The subject map files contain mappings from
RIC names to subject names. If local or global subject map files are specified and exist, they are read
at startup and are used to pre-load RIC to subject mappings. The global subject map file is a read-only
file. The local subject map file is a writable file. If SFC guesses the wrong subject for a RIC, the RIC
and its correct subject are written to the local subject map file. This will prevent SFC from guessing
incorrectly in the future. There are default subject map files, so that feature is disabled by default. The
*globalSubjectMapFile and *localSubjectMapFile configuration variables can be used to specify the
map files.
SFC's subject map file has the same format as the one used by SSL Adapter. The following is an
example of contents from a subject map file:
1.AV.PA LINK.1^AV.PA
0001.HK REC.0001.HK
The default record customizer has the following configuration.
• *sectorList - A list of sectors for the default record customizer to try after the initial guess (in the
order of the list).
• *localSubjectMapFile - A local file that the default record customizer uses to record RIC to
subject mappings that were not guessed correctly on the first try. The customizer can also read
from this file for all the correct subject mappings for its use. This file is disabled by default.
• *globalSubjectMapFile - A read-only file that the default record customizer reads for correct RIC
to subject mappings. This file is not changed by the customizer.
• *subjectMapSize - Specify the size of the hash table for the subject map.
• *number_of_items - Specify the size of the hash table for RTRServiceCustomizer

SFC Developer’s Guide 316


5 SFC IMPLEMENTATION DETAILS

Other Default Customizers


The default record publishing customizer for RTIC employs the same algorithm that is used by the
SFC record subscriber for its initial guess. This customizer also supports reading subjects from the
local and global subject map files, but it does not record subjects to the local subject map file. A
publishing customizer does not retry because its first subject is always assumed to be correct. If the
publishing customizer is changed, all subscription applications should be changed to use the same
customizer to ensure they can produce the same RIC to subject mapping.
The default page customizer for RTIC(SASS2) does not retry or record. It always uses the PAGE
sector, unless the default sector is overridden in configuration or programmatically.
The default customizer for RMDS subscribers and publishers does not retry or record. It always uses
the sector downloaded from the RTIC, unless the setDefaultSector() method or the *serviceProvider
or *defaultSector configuration variables are used. If the *serviceProdiver configuration variable is
set to RTIC, the sector will default to "ANY".
The default customizer for RMDS insert services does not retry or record. It always uses the "ANY"
sector, unless the setDefaultSector() method or the *dataProvider or *defaultSector configuration
variables are used.

5.5.7.3 Setting defaultSector to "."


When the default customizers do not satisfy the needs of an application, SFC has a simple way for
applications to request subject names. If the default sector is set to "." (either through
setDefaultSector() or *defaultSector) then the SFC will use a simplified subject mapping scheme.
SFC will still use the service name as the first part of the subject name. The item name will be used as-
is for the rest of the the subject name. For example, with service RDF and record item name
REC.IBM.N, the subject will be RDF.REC.IBM.N. For record item name ANY.IBM.N, the subject will be
RDF.ANY.IBM.N.
Setting the defaultSector to "." eliminates the need to write a RTRTIBCustomizer (described in
section 5.5.7.4) for most applications. However, it has a couple of disadvantages related to
infrastructure portability and migration:
1. Applications written to request records using the last three parts of the subject name will only
work with the TIB implementation. The records will not exist on Triarch.
2. Sector names differ between RTIC/SASS2 and SASS3 infrastructures, so applications written
to request REC.IBM.N for an RTIC(SASS2) infrastructure will not work with RTIC(SASS3),
which would require ANY.IBM.N.

SFC Developer’s Guide 317


5 SFC IMPLEMENTATION DETAILS

Since page services have simpler sector schemes (i.e. its either PAGE or ANY), the default sector of
"." is only supported for record subscription and publishing services. The *defaultSector configuration
variable can still be used with page services to set the actual sector.

5.5.7.4 Overriding the TIB Customizer


In cases where the default mapping algorithm does not produce the appropriate 4-part subject name,
the application programmer may create a subclass of RTRTIBCustomizer to override methods in the
RTRTIBCustomizer class to provide the name mapping required by the application. To do this, the
programmer writes a new class that inherits from RTRTIBCustomizer and re-implements one of the
public methods. The RTRTIBCustomizer base class provides default implementations for all methods,
so only some of the methods must be overridden in the customizer subclass. This new customizer can
then be given to the service using the setTIBCustomizer() method on RTRTIBRTRecordService,
RTRTIBPageService, or RTRRTFieldToTIBRecordService. Since the customizer is set right after the
service is constructed, the TIB implementation specific code can be in one place, and the rest of the
application can use the generic RTRRTRecordService.
The RTRTIBCustomizer::makeSubject() method is called by the SFC publishing service to map a
given service name and record symbol into a valid 4-part subject. To do this, it first calls the
RTRTIBCustomizer::getSectorForSymbol() which parses the SFC symbol to find the proper sector
value. Then the RTRTIBCustomizer::getExchangeForSymbol() method is called to determine the
exchange value. See the SFC Reference Manual for more information about RTRTIBCustomizer
methods. Figure 5.2 shows how and when the methods are called in a RTRTIBCustomizer.
A user-defined customizer may override one or all of these methods to modify the mapping algorithm
and ensure the expected TIB subject is published.
For simple subject customization, a RTRTIBCustomizer is not needed. RTRTIBRTRecordService,
RTRTIBPageService, and RTRRTFieldToTIBRecordService have setDefaultSector() and
setDefaultExchange() methods along with defaultSector and defaultExchange configuration
variables to which the sector and exchange portions of the subject can be fixed.

SFC Developer’s Guide 318


5 SFC IMPLEMENTATION DETAILS

Figure 5.2: RTRTIBCustomizer Usage

SFC Developer’s Guide 319


5 SFC IMPLEMENTATION DETAILS

5.5.7.5 Next and Previous Page Names


In Triarch and RMDS, page services typically append a ’+’ to indicate the next page and a ’-’ to indicate
the previous page. In RTIC(SASS2), page services use ’n’ for next and ’p’ for previous. The SSL
implementation requires + and -, but the TIB implementation will automatically map n, p, +, and - to the
correct character for the RMDS infrastructure.
While SFC maps n, p, +, and -, it also provides configuration for overriding this behavior. The follow
configuration entries show how to additionally map x to next and y to previous.
*nextChars : n+x
*prevChars : p-y

5.5.7.6 News Headlines


NOTE: This feature is deprecated since SFC 4.5.1.L3 which dropped support for TIB infrastructure.

N2_UBMS is a special RIC in the RMDS and Triarch infrastructures to deliver news headlines, alerts,
and corrections. In the TIB infrastructure this data is typically delivered in seven separate subjects. For
a service RSF, these subjects would be:
RSF.BRCAST.NEWS2K_ALERT.NaE
RSF.BRCAST.NEWS2K_HL.NaE
RSF.BRCAST.NEWS2K_SUB_HL.NaE
RSF.BRCAST.NEWS2K_CORRECT.NaE
RSF.BRCAST.NEWS2K_CORECTD.NaE
RSF.BRCAST.NEWS2K_DELETE.NaE
RSF.BRCAST.NEWS2K_EXPIRE.NaE
For the TIB infrastructure, C++ Edition supports mapping the single N2_UBMS subject to the seven
TIB subjects. This allows SFC applications to request N2_UBMS from any infrastructure. When the
application subscribes to N2_UBMS, SFC will subscribe to each of seven news subjects. Subject-
based entitlement checks will be performed on each of the TIB news subjects. Data from any of those
subjects will be forward to clients of the N2_UBMS record.
N2_UBMS mapping is enabled by default, but it can be disabled by setting the *newsEnabled
configuration variable to false. The *newsSymbol configuration variable can be used to change the
application requested RIC from N2_UBMS.
When forwarding news subjects to the N2_UBMS record, SFC maps the subject to a numeric value
stored in the DSPLY_NAME field. The mapping can be configured using the *newsInstrumentList.

SFC Developer’s Guide 320


5 SFC IMPLEMENTATION DETAILS

Applications using the TIB infrastructure still have the option of subscribing directly to the seven news
RICs: NEWS2K_ALERT, NEWS2K_HL, NEWS2K_SUB_HL, NEWS2K_CORRECT,
NEWS2K_CORECTD, NEWS2K_DELETE, and NEWS2K_EXPIRE.

NOTE: Applications on Triarch and RMDS infrastructures must use N2_UBMS.

The *newsSectorList configuration variable provides a list of sectors that the default record
customizer for TIB uses with news subjects. The *newsPrefix configuration variable is used to
determine which subjects use *newsSectorList and which use the *sectorList.
News configuration has the following defaults:
*newsInstrumentList: NEWS2K_ALERT.NaE 1, NEWS2K_HL.NaE 2, NEWS2K_SUB_HL.NaE 3,
NEWS2K_CORRECT.NaE 4, NEWS2K_CORECTD.NaE 5, NEWS2K_DELETE.NaE 7,
NEWS2K_EXPIRE.NaE 8
*newsSectorList: BRCAST, INTERACTIVE
*newsPrefix: NEWS2K_
*newsSymbol: N2_UBMS
*newsEnabled: true

5.5.7.7 Configuration
The complete list of customizer configurations is shown below with the default values. All values can
be configured on a per service basis.
The default record subscription customizer for TIB has the following configuration:
*sectorList: REC, PAGE,LINK
*newsSectorList: BRCAST,INTERACTIVE
*newsPrefix: NEWS2K_
The default record subscription and publishing customizers for TIB have the following configuration.
*localSubjectMapFile:! disabled
*globalSubjectMapFile:! disabled
*subjectMapSize: 1000! size of subjectMap hash table
*number_of_items: 503! size of RTRServiceCustomizer hash table
TIB page services have the following default configuration:
*defaultSector: PAGE
*defaultExchange: NaE

SFC Developer’s Guide 321


5 SFC IMPLEMENTATION DETAILS

TIB record services have the following default configuration:


*defaultSector: ! the guess algorithm will be used
*defaultExchange: NaE

5.5.8 Page Services

5.5.8.1 Page Records


Most of the time, the LINK and REC sectors are used by record services to receive data from market
datafeeds. TIB effects pages use the PAGE sector. Effects pages originate from a ANSI stream page
feed (e.g. Telerate) before being logicized by TIB feed handlers. They are different than IDN page
records because they contain attribute information. Despite using the same PAGE sector, effects
pages should be processed by the SFC page model.
Some items within the PAGE sector are also available from Marketfeed record services. These market
data items are called page records. Page records are pages whose data has already been separated
into rows and whose rows have been put into fields before being processed by the datafeed. They do
not contain attribute information and should be processed through the SFC record model. SFC’s page
model is intended for page services that have attribute information (e.g. bold, inverse), such as
TELERATE and TULLETT.
On Triarch and RMDS the SFC page model must be used for ANSI data. SFC’s page model will
decode the ANSI data and provide a simple interface for querying attributes and data. The SFC page
model cannot be used for IDN data, even if the conceptual data type of the Marketfeed is a "page." IDN
data in a page format is sometimes called a "page record", because the record contains fields named
as rows (ROW64_1, ROW80_2, etc.)
On TIB Classic, it is a little different because all data is logicized to look like a record. The SFC page
model should be used for "effects" pages (the TIB terminology for pages with attributes). The SFC
page model will decode the attributes and present the same interface as if the data had come
fromTriarch or RMDS. The SFC record model could also be used for effects pages. However this is not
recommended because the attribute information will left encoded in a binary format. Also, the
application would only work on TIB and would not work on RMDS or Triarch. The SFC page model
could be used for IDN page records. This works because the TIB feed handler has normalized the
data. The RTRPages will not have attribute information because IDN pages do not have attributes.
Using the SFC page model for IDN page records on TIB is not recommended because the application
would only work on TIB and would not work on RMDS or Triarch.

SFC Developer’s Guide 322


5 SFC IMPLEMENTATION DETAILS

5.5.8.2 Effects Page Attribute Encoding


Some page datafeeds on a TIB market data system do not use the TIB standard method for encoding
attributes. Instead of sending color information in the color bytes, they encode colors in the bytes
reserved for format attributes (bold, italics, etc.). SFC provides a mechanism for automatically
mapping data attributes to the correct semantic color attributes. An example attribute map for the
GARBAN service is defined in /var/triarch/charMapFile.cnf. Separate attribute maps can be specified
in this file for each service. Attribute mapping can also be turned off through SFC configuration.
Attribute mapping is enabled by default, so it should be disabled, or an attribute map for the service
should be added to the file.
Like attribute mapping, character set mapping is used to automatically change the underlying page
region data. Most applications do not have to worry about character set mapping. However, if a page
uses extended ASCII characters (above 127), the application may need to change the character to
something that can be more accurately displayed using the character sets available to the application.
Several example character set maps are defined in /var/triarch/charMapFile.cnf. Character set
mapping is enabled by default, but it can also be disabled through configuration.
The following standard SFC configuration variables can also be used to configure the attributes for TIB
page services:
• *mapAttributes - should attribute mapping be enabled? (default is true)
• *mapCharacters - should character set mapping be enabled? (default is true)
• *attrMapFile - the filename of the character set and attribute map configuration file (default is /
var/triarch/charMapFile.cnf)
• *sslPageCompatible - should a mock feed status line (sent with pages on Triarch) be added to
the bottom of the page? (default is false)
• *vendorName - the name to be used in the sslPageCompatible feed status line
• *defaultCharSet - the default character set (default is ’B’ for US_ASCII)

5.5.8.3 ANSI Page Sizes


ANSI stream based pages from RMDS or Triarch have a default size of 80 columns by 25 rows. To
support larger pages, SFC must be configured with the page size. SFC uses the following
configuration variables:
*rowsInPage : 25

SFC Developer’s Guide 323


5 SFC IMPLEMENTATION DETAILS

*columnsInPage : 80
The Source Distributor must also be configured with those settings.

5.5.9 Inserts and Contributions


The terms ’contribution’ and ’insert’ are generally synomous. There are differences as to how to
implement inserts with respect to the various infrastructures (Triarch, RMDS, and Classic TIB) and
how different infrastructures handle inserts and contibutions. The SFC insert model is supported on
the RMDS and Triarch infrastructures. Local publishing (sending data through an RVD to a TIC or
RTIC using a service specified in the TIC’s configuration file as a broadcast service) is used to
contribute data using the Classic TIB infrastructure.

5.5.9.1 Inserts and Triarch


The contribution is sent through a Sink Distributor and a Source Distributor. The data in the
contribution is formatted as Marketfeed. SFC’s insert model is used to impliment contributions on
Triarch.

5.5.9.2 Inserts and RMDS (SASS3)


Contributions are sent through the RVD, RTIC, and Source Distributor. The contribution service is
specified as an interactive service in the RTIC’s configuration file. The data in the contribution is
typically formatted as Marketfeed. The behavior is very similar to that for Triarch. SFC’s insert model
must be used to send contributions.The primary difference between contributions on RMDS and
Triarch is the RVD vs. Sink Distributor connection.

5.5.9.3 Inserts and Classic TIB (SASS2 and SASS3)


NOTE: This feature is deprecated since SFC 4.5.1.L3 which dropped support for TIB infrastructure.

Contributions are sent the same way that local published data is sent. Like local publish services, the
contribution service is specified as a broadcast service in the TIC’s configuration file. The difference is
a TIB contribution server (e.g. MarketLink) happens to be consuming the locally published data. It
validates the data and forwards it through the contribution infrastructure. SFC’s insert model cannot be
used; the record publishing model must be used to send contributions. The application will never
receive an ACK or NAK because TIB contribution servers do not send them. SFC publishes the data in

SFC Developer’s Guide 324


5 SFC IMPLEMENTATION DETAILS

TIBMsg self-describing format and the TIC converts the data to a QForm based on the record template
number provided to SFC.

5.5.10 Connection and Session Parameters


See section 4.8.1 for information on the Connection model and for examples of how to set connection
parameters programmatically.

5.5.10.1 RTIC
The standard Rendezvous connection parameters can be set using the constructor or through the
RTRConfigDb:
• *service - which service group should be used. Default value is NULL which means the default
Rendezvous service will be used.
• *network - which network interface should be used. Default value is NULL which means the
primary network interface for the host computer will be used.
• *daemon - location of the Rendezvous daemon used to establish communication. Default value
is NULL which means the local daemon on TCP socket 7500 will be used.
• *updateService - which TMF service group should be used. Default value is NULL which means
the TMF default Rendezvous service will be used.
• *updateNetwork - which TMF network interface should be used. Default value is NULL which
means the TMF primary network interface for the host computer will be used.
• *updateDaemon - location of the TMF Rendezvous daemon used to establish communication.
Default value is NULL which means the TMF local daemon on TCP socket 7500 will be used.

NOTE: If updateService, updateNetwork, and updateDaemon are all NULL, then TMF is disabled
by default.

Several SFC-specific parameters can also be set


• *enableEntitlements - See section 5.3.2. This parameter is used to enable or disable
entitlements.

SFC Developer’s Guide 325


5 SFC IMPLEMENTATION DETAILS

Entitlements are checked on both subscriber and publisher. The entitlements profile is loaded
after the data dictionary is complete. While the data dictionary and entitlements profile are
downloading, the subscription is not allowed and the service is not available.
• *reconnect_interval - If the Rendezvous connection fails due to a recoverable condition, this
value is used to schedule a reconnection attempt. The default value is 5 (seconds).
• *slowconsumer_interval - If the Rendezvous connection fails due to a slow consumer advisory
message, this value is used to schedule a reconnection attempt. The default value is 20
(seconds). This is slower than reconnect_interval to allow the consumer’s machine more
opportunity to catch up. If the value is less than or equal to zero, the RVD connection will not be
terminated when a slow consumer advisory message is received.
• *username - the DACS username used for entitlement checking. This option only applies when
entitlements are enabled and the connection is a SASS3 connection. See section 5.3.3 in this
manual or see RTRTIBConnection in the SFC Reference Manual for details.
• *enablePingSubscription - Two purposes of this configuration are: (1) for SASS2 and SASS3, to
enable RTRRTFieldToTIBRecordService to send heartbeats to the RTIC. These heartbeats
provide the RTIC to determine if the SFC publisher goes down. This mechanism will incorporate
with RTIC’s BC_DQA_MODE and SFC’s *groupId configuration. (2) for SASS2 only, these
heartbeats also provide the SFC publisher with a mechanism to determine if the RTIC goes down.
It does this by subscribing to its own ping over the same Rendezvous session on which it is
publishing. This configuration variable must be set to false when the RTIC is using different
values for the RVx_OUTPUT_* and RVx_PUBLISH_* RTIC configuration parameters.
Specifically, *enablePingSubscription must be set to false when:
O the RV2_OUTPUT_* and RV2_PUBLISH_* parameters are set in the RTIC’s configuration file
O the RV3_OUTPUT_* and RV3_PUBLISH_* parameters are set in the RTIC’s configuration
file
O sending contributions
O the RTIC has a partitions.cf that filters out the PING sector
• *pingInterval - the frequency, in seconds, that a heartbeat will be sent to the RTIC. The default
value is 10 seconds and it can be set on a per service basis. If RTIC’s BC_DQA_MODE is set to
TRUE and SFC’s *groupId is set, *pingInterval must be less than the RTIC’s
FEED_FAIL_TIMEOUT. Otherwise the RTIC will think that the publisher has died and will mark all

SFC Developer’s Guide 326


5 SFC IMPLEMENTATION DETAILS

items stale. In addition, setting *pingInterval to 0 is equivalent to setting


*enablePingSubscription to FALSE.
See RTRTIBConnection or RTRTIBServicePoolFactory in the SFC Reference Manual for further
details on all of these parameters.

5.5.10.2 SSL
Most SSL client connection parameters are configured in the sslapi.cnf. The following values can be
set using the SFC configuration file for a SSL Connection:
• *username - the DACS username used when making a sink connection. See section 5.3.3 in this
manual or see RTRSSLConnection in the SFC Reference Manual for details.
• *mountRetryInterval - the number of seconds to wait before retrying an initial connection to a
Sink Distributor. The default value is 5 (seconds).
The following values can be set using the SFC configuration file for a SSL Connection Server:
• *username - the DACS username used when making a sink connection. See section 5.3.3 in this
manual or see RTRSSLConnectionServer in the SFC Reference Manual for details.
• *ipcServerName - the name of the well-known port to open for accepting connections
• *maxSessions - maximum number of connections accepted from other applications
• *reconnect_interval - The default value is 10 (seconds).
• *enableEntitlements - See section 5.3.2. This parameter is used to enable or disable
entitlements.
• *tcpNoDelay - The *tcpNoDelay parameter controls the use of TCP_NODELAY socket option
(which the Nagle algorithm disabled). SFC normally does not use TCP_NODELAY socket by
default; this improves overall performance but it might briefly delay transmission of smaller
packets. If the delay is undesirable or unacceptable, setting *tcpNoDelay to true may reduce
end-to-end latency but it will consume more CPU usage.
The following values can be set using the SFC configuration file for a SSL publisher session:
• *dispatchInterval - The parameter is interval time publisher session for dispatching event for
event queue. Setting the configuration lower may improve latency under high update rates but
would result in more CPU usage. The default value is 25 (milliseconds); the lowest value can be
10.

SFC Developer’s Guide 327


5 SFC IMPLEMENTATION DETAILS

5.5.11 Using Rendezvous 6 Library with the SFC


The Rendezvous 6 library and functions can be used in an application that also uses SFC, with the
following constraints:
• Application code using Rendezvous 6 must run in a separate thread than Rendezvous 5 or SFC
code.
All code that calls Rendezvous 6 functions or receives callbacks from Rendezvous 6 library must
run in a different thread from the SFC or code using Rendezvous 5.
• Your build environment must reference an Rendezvous 6 library and include associated header
files.
These are not included in the C++ Edition.
This release includes a simple example program that uses both Rendezvous 6 and SFC in the same
application. The example can be found in the <INSTALL_DIR>/sfc/examples/rvinterop directory of
the installation.

5.5.12 Using Rendezvous 5 Library with the SFC


Rendezvous 5 functions may be called directly in an application that also uses SFC classes, with the
following restrictions:
• SFC and Rendezvous 5 code must run in the same thread.
All SFC objects, Rendezvous functions and any application code receiving callbacks from either
SFC or Rendezvous or calling SFC or Rendezvous methods MUST be run in the same thread.
Since the SFC implements the Rendezvous event manager and that code is not thread-safe, all
code using the Rendezvous event manager must be run in the same thread.
However, all code that calls Rendezvous 6 functions or receives callbacks from Rendezvous 6
library must run in a different thread from the SFC or code using Rendezvous 5.
• Applications using SFC must not link in the Rendezvous 5 ’C’ library.
The SFC library contains the Rendezvous 5 library objects found in the librvcst.a and libtibrv.a
libraries. Also, the SFC implements the Rendezvous event manager functions, so your
application does not need to include an event manager implementation.

SFC Developer’s Guide 328


5 SFC IMPLEMENTATION DETAILS

If your application needs to implement the main-loop, it needs to implement the SFC event notifier
rather than the Rendezvous event manager. (See the RTRSelectNotifier and
RTRWindowsNotifier class references for examples of how SFC notifiers can be implemented.
Also note that the source code for all notifier implementations is provided in this product
package.)
• Your build environment must include the Rendezvous 5 header files from Rendezvous version
5.3.
These header files are not included in the C++ Edition.

SFC Developer’s Guide 329


5 SFC IMPLEMENTATION DETAILS

5.6 Configuration

5.6.1 SSL Library Configuration


Configuration of the SSL implementation of SFC falls into two realms:
1. SSL Library Configuration - low-level configuration of SSL library parameters
2. SFC Configuration - all other configuration
The SSL library configuration file consists of a number of configuration variable settings which may be
specified on a per installation, per hosts, or per application name basis. Configuration variables cover
connection parameters, low-level performance tuning, and tracing.
SSL library configuration can be done through sslapi.cnf. The sslapi.cnf file is preferred over the
ipcroute file. The ipcroute file is still supported for backwards compatibility, but all of its functionality is
also included in sslapi.cnf. The sslapi.cnf file takes priority over ipcroute, so ipcroute should not be
used to avoid confusion. The ipcroute file is not installed in this version of SFC.
The SSL library will look for a configuration file in the following locations:
1. in the local directory (./sslapi.cnf)
NOTE: A local file will take precendence over one specifid by a registry entry or environment
variable.
2. if a file is not found in the local directory,
\HKEY_LOCAL_MACHINE\Software\Reuters\SSL\SSLAPI_CONFIG registry entry (Windows only)
3. SSLAPI_CONFIG environment variable
If the sslapi.cnf file does not exist, the ipcroute file will be located per SSL 4.0 guidelines.
Note that the registry entry and the environment variable can be used to set the file location and name
to the same one used by SFC’s RTRXFileDb. That way, only one configuration file is needed.
See Appendix B.6 for a detailed description of the sslapi.cnf file.

5.6.2 SFC Configuration Summary


The following tables summarize SFC configuration variables and provide a reference for more
information about them. Additional low-level SSL configuration variables are detailed in Appendix B.6.

SFC Developer’s Guide 330


5 SFC IMPLEMENTATION DETAILS

Variable ClassIds Default Reference

display_configuration Logger false Reference Manual:


RTRDefaultLogger

recordServices SSLServicePoolFactory None Reference Manual:


RTRMDServicePoolFactory

rtPageServices SSLServicePoolFactory None Reference Manual:


RTRMDServicePoolFactory

timeSeriesServices SSLServicePoolFactory None Reference Manual:


RTRMDServicePoolFactory

pageServices TIBServicePoolFactory None Reference Manual:


RTRMDServicePoolFactory

recordServices TIBServicePoolFactory None Reference Manual:


RTRMDServicePoolFactory

timeSeriesServices TIBServicePoolFactory None Reference Manual:


RTRMDServicePoolFactory

pageServices SSLServicePoolFactory None Reference Manual:


RTRMDSServicePoolFactory

ipcServerName SSLConnectionServer None Reference Manual:


RTRSSLConnectionServer

maxSessions SSLConnectionServer None Reference Manual:


RTRSSLConnectionServer

insert_timeout InsertService.SSLInsertService constructor or 30, config Reference Manual:


overrides constructor SSLInsertService

insert_timeout InsertService.TSAInsertService constructor or 30, config Reference Manual:


overrides constructor SSLInsertService

closeInactiveItemAsRecoverable SSLPublisherRecordService false ReferenceManual:


RTRFieldToSSLRecordService

criteriaName RTRSSLSessionPublisherRecordSer- triarch section 4.2.4.1


vice

pubSubjectPrefix RTRMDAPIInterface _TIC section 4.2.4.2

defaultBgColor ProxySSLPageService 0 section 4.3.4.3

defaultFgColor ProxySSLPageService 7 section 4.3.4.3

Table 5.13: Configuration Variables

SFC Developer’s Guide 331


5 SFC IMPLEMENTATION DETAILS

Variable ClassIds Default Reference

enableColors ProxySSLPageService true section 4.3.4.3

defaultBgColor RTRProxyTIBPageService 0 section 4.3.4.3

defaultFgColor RTRProxyTIBPageService 7 section 4.3.4.3

enableColors RTRProxyTIBPageService true section 4.3.4.3

requestTS1RealTime RTRTS1Record false section 4.5.2

protocol TIBConnection SASS3 section 4.8.1.2

defaultFileAction.file Logger log.out section 4.8.6.4

defaultFileAction.flush Logger true section 4.8.6.4

defaultFileAction.max_bytes Logger 10000 section 4.8.6.4

defaultFileAction.selector Logger *.info section 4.8.6.4

defaultFileAction.truncate Logger false section 4.8.6.4

enable Logger true section 4.8.6.4

install_file_action Logger true section 4.8.6.4

install_stderr_action Logger false section 4.8.6.4

install_system_action Logger false section 4.8.6.4

priority Logger 100 section 4.8.6.4

selector Logger *.info section 4.8.6.4

enableEntitlements SSLConnectionServer false section 5.3.2

username SSLConnectionServer None section 5.3.3

username TIBConnection None section 5.3.3

DACS_log_file_path DACSConnection ./ section 5.3.6

DACS_log_file_size DACSConnection 255 section 5.3.6

DACS_log_flush_interval DACSConnection 60 section 5.3.6

Table 5.13: Configuration Variables (Continued)

SFC Developer’s Guide 332


5 SFC IMPLEMENTATION DETAILS

Variable ClassIds Default Reference

DACS_retry_connection_interval DACSConnection 60 section 5.3.6

DACS_user_login_retry_interval DACSConnection 1 section 5.3.6

DACS_user_login_wait_period DACSConnection 60 section 5.3.6

dacsHashTableSize DACSEntitlementSystem None section 5.3.6

permField RTRSASS3Interface PROD_CATG section 5.3.6

serviceId SSLPublisherRecordService None section 5.3.6

enableEntitlements SSLConnectionServer section 5.3.2

number_of_items PageService 101 section 5.4.2.1

number_of_items SSLMDService.SSLRTPageService 503 section 5.4.2.1

number_of_items SSLMDService.SSLRTRecordService 503 section 5.4.2.1

number_of_items SSLPublisherRecordService 101 section 5.4.2.1

number_of_items TIBPublisherRecordService 101 section 5.4.2.1

number_of_items TIBRTRecordService 503 section 5.4.2.1

number_of_items DACSEntitlementSystem 101 section 5.4.2.1,section 5.3.6

fids_per_record SSLPublisherRecordService 150 section 5.4.3

fids_per_record TIBPublisherRecordService 150 section 5.4.3

fids_per_record TIBRTRecordService 150 section 5.4.3

request_queue*initial_pending_limit VJRequestQueue 10 section 5.4.4.1

request_queue*limit_multiplier VJRequestQueue 2 section 5.4.4.1

request_queue*max_pending_limit VJRequestQueue 100 section 5.4.4.1

request_item_config* RTRProxyTIBRTRecordService 300 section 5.4.4.2


retry_cap_seconds

request_item_config* RTRProxyTIBRTRecordService 2 section 5.4.4.2


retry_multiplier

Table 5.13: Configuration Variables (Continued)

SFC Developer’s Guide 333


5 SFC IMPLEMENTATION DETAILS

Variable ClassIds Default Reference

request_item_config* RTRProxyTIBRTRecordService 5 section 5.4.4.2


retry_seconds

request_item_config* RTRProxyTIBRTRecordService 20 section 5.4.4.2


timeout_seconds

imageRequestOpenLimit SSLPublisherRecordService infrastucture default section 5.4.5

imageInterval SSLSession 100 section 5.4.5.2

imagesPerInterval SSLSession 30 section 5.4.5.2

traceLevel RTRProxyTIBPageService 0 section 5.4.6

traceLevel RTRProxyTIBRTRecordService 0 section 5.4.6

traceLevel RTRTIBPublisherRecordService 0 section 5.4.6

item_debug SSLMDService false section 5.4.6

traceLevel SSLPublisherRecordService 0 section 5.4.6

tiblogfile RTRSASS3Interface "SASS3.log" section 5.4.7

mountTrace SSLDispatcher false section 5.4.7

sslLogFile SSLInterface SSL.log section 5.4.7

sslLogFileSize SSLInterface 10000 section 5.4.7

reconnect_interval SSLConnectionServer 10 section 5.5.10

mountRetryInterval SSLDispatcher 5 section 5.5.10

daemon TIBConnection "" section 5.5.10

network TIBConnection "" section 5.5.10

reconnect_interval TIBConnection 5 section 5.5.10

service TIBConnection "" section 5.5.10

slowconsumer_interval TIBConnection 20 section 5.5.10

updateDaemon TIBConnection "" section 5.5.10

updateNetwork TIBConnection "" section 5.5.10

Table 5.13: Configuration Variables (Continued)

SFC Developer’s Guide 334


5 SFC IMPLEMENTATION DETAILS

Variable ClassIds Default Reference

updateService TIBConnection "" section 5.5.10

enablePingSubscription TIBDistribution true section 5.5.10.1

pingInterval TIBDistribution 5 section 5.5.10.1

tcpNoDelay SSLConnectionServer false section 5.5.10.2

dispatchInterval RTRSSLPublisherSession 25 section 5.5.10.2

dropSeqNo ProxyTIBRTRecordService false section 5.5.2

decimalSize RTRBaseTIBFidDB 17 section 5.5.2, section 5.5.2.2

sendSymbolFields RTRTIBMsgEncoder true section 5.5.2

enableNextChainHeaderAsString RTRTIBMsgEncoder true section 5.5.2

mfencoder RTRTIBPublisherRecordService false section 5.5.2

srcExpandsEnumFields RTRProxyTIBRecordService false section 5.5.2.1

srcExpandsEnumFields SSLMDService.SSLRTRecordService false section 5.5.2.1

useTemplates RTRTIBPublisherRecordService true section 5.5.3

enum_file_path FileFidDb None, section 5.5.4.1

fid_file_path FileFidDb None section 5.5.4.1

fidDbInterval SSLFidDb 20 section 5.5.4.1

fidDbLocation SSLFidDb None section 5.5.4.1

enum_file_path TIBFidDb None, section 5.5.4.1

fid_file_path TIBFidDb None section 5.5.4.1

fidDbInterval TIBFidDb 20 section 5.5.4.4

fidDbLocation TIBFidDb None section 5.5.4.4

fidDbType TIBFidDb None section 5.5.4.4

allowUpdatesToChangeStaleToOk ProxyTIBRTRecordService false section 5.5.5.1

Table 5.13: Configuration Variables (Continued)

SFC Developer’s Guide 335


5 SFC IMPLEMENTATION DETAILS

Variable ClassIds Default Reference

groupId TIBDistribution 0 section 5.5.5.1

notFoundAsRecoverable TIBItemService true section 5.5.5.1

dataLossInboundInterval TIBConnection 0 section 5.5.5.2

dataLossOutboundInterval TIBConnection 0 section 5.5.5.2

forceInfrastructureRecovery TIBItemService false section 5.5.5.4

forceSFCDrivenRecovery TIBItemService false section 5.5.5.4

enableDynamicTimeSeriesServices SSLServicePoolFactory true section 5.5.6.1

enableDynamicPageServices SSLServicePoolFactory true section 5.5.6.1

enableDynamicRTPageServices SSLServicePoolFactory true section 5.5.6.1

enableDynamicRTRecordServices SSLServicePoolFactory true section 5.5.6.1

enableDynamicInsertServices SSLServicePoolFactory true section 5.5.6.1

enableDynamicTimeSeriesServices TIBServicePoolFactory true section 5.5.6.1

enableDynamicPageServices TIBServicePoolFactory true section 5.5.6.1

enableDynamicRTRecordServices TIBServicePoolFactory true section 5.5.6.1

enableDynamicInsertServices TIBServicePoolFactory true1 section 5.5.6.1

dataType ServiceStatus None section 5.5.6.2

serviceProvider ServiceStatus None section 5.5.6.2

serviceStatusInterval ServiceStatus 15 section 5.5.6.2

traceServiceStatusInfo ServiceStatus False section 5.5.7.2

number_of_items DefaultRecordCustomizer 503 section 5.5.7.2

sectorList DefaultRecordCustomizer REC, PAGE, LINK section 5.5.7.2

defaultSector InsertService.TSAInsertService ANY section 5.5.7.2

defaultExchange RTRProxyTIBPageService NaE section 5.5.7.2

Table 5.13: Configuration Variables (Continued)

SFC Developer’s Guide 336


5 SFC IMPLEMENTATION DETAILS

Variable ClassIds Default Reference

defaultSector RTRProxyTIBPageService PAGE section 5.5.7.2

defaultExchange RTRProxyTIBRecordService NaE section 5.5.7.2

globalSubjectMapFile ServiceCustomizer None section 5.5.7.2

localSubjectMapFile ServiceCustomizer None section 5.5.7.2

subjectMapSize ServiceCustomizer 1000 section 5.5.7.2

defaultSector RTRProxyTIBRecordService "" section 5.5.7.2, section 5.5.7.3

defaultSector RTRTIBPublisherRecordService "" section 5.5.7.2, section 5.5.7.3

nextChars RTRProxyTIBPageService +n section 5.5.7.5

prevChars RTRProxyTIBPageService -p section 5.5.7.5

newsSectorList DefaultRecordCustomizer BRCAST, INTERACTIVE section 5.5.7.6

newsEnabled RTRProxyTIBRecordService true section 5.5.7.6

newsSymbol RTRProxyTIBRecordService N2_UBMS section 5.5.7.6

newsPrefix ServiceCustomizer NEWS2K_ section 5.5.7.6

newsInstrumentList TIBNews NEWS2K_ALERT.NaE 1, section 5.5.7.6


NEWS2K_HL.NaE 2,
NEWS2K_SUB_HL.NaE 3,
NEWS2K_CORRECT.NaE 4,
NEWS2K_CORECTD.NaE 5,
NEWS2K_DELETE.NaE 7,
NEWS2K_EXPIRE.NaE 8

attrMapFile RTRProxyTIBPageService /var/triarch/charMapFile.cnf section 5.5.8.2

charMapFile RTRProxyTIBPageService /var/triarch/charMapFile.cnf section 5.5.8.2

defaultCharSet RTRProxyTIBPageService B section 5.5.8.2

mapAttributes RTRProxyTIBPageService true section 5.5.8.2

mapCharacters RTRProxyTIBPageService true section 5.5.8.2

sslPageCompatible RTRProxyTIBPageService false section 5.5.8.2

vendorName RTRProxyTIBPageService "" section 5.5.8.2

Table 5.13: Configuration Variables (Continued)

SFC Developer’s Guide 337


5 SFC IMPLEMENTATION DETAILS

Variable ClassIds Default Reference

columnsInPage PageService 80 section 5.5.8.3

rowsInPage PageService 25 section 5.5.8.3

Table 5.13: Configuration Variables (Continued)


1. For TIC/SASS2 infrastructure, service must be added to the RTRTIBServicePoolFactory manually or through con-
figuration.

SFC Developer’s Guide 338


APPENDIX A: GLOSSARY

Active A market data item is initially in this state when it is created. It remains
active until it is closed or destroyed.
ANSI The American National Standards Institute (ANSI) develops standards
widely used as guidelines by US firms. Data processing standards devel-
oped from ANSI range from the definition of ASCII to the determination of
overall datacom system performance.
ANSI Sequence A string of characters that invokes a mode or status change in the display
system. ANSI sequences start with an ESC character (1B hex) and then
follow one of several patterns. The receiving device must recognize these
patterns and act upon the supported sequences while ignoring unsup-
ported sequences. ANSI sequences can refer to position or attribute infor-
mation.
ANSI Page The Triarch name for Effects Page. Pages on Triarch are delivered as a
stream of ANSI encoded data. See also Page.
Attributes See Page Attributes.
CBE Content Based Entitlements
Client A component that receives events from SFC.
Client Application An application that receives data and events from a market data infrastruc-
ture.
CMON A TIB infrastructure component that monitors the status of other infrastruc-
ture components.
Consumer See Subscriber, Client Application, Sink Client.
Contribution See Insert.

SFC Developer’s Guide 339


APPENDIX A: GLOSSARY

DACS The Data Access Control System is a entitlement tool that allows custom-
ers to automatically control who is permitted to use which sets of data in
the customer’s financial information management system. In this way, the
customer can demonstrate to information providers and vendors how
many people are using which sets of data.
Data Dictionary See FID Database.
Distribution Layer The TIBCO Rendezvous network that consists of the RVDs of the RTIC
and end-user programs.
DQA Data Quality Assurance. The TIB infrastructure uses the CMON process to
send heartbeats to other market data components. If one of them does not
respond, a DQA message is broadcast to indicate that the data might be
stale.
Effects Pages An ANSI Page, after it has been converted into a Logical Page to be
broadcast on a TIB market data system.
Entitlement Code If a vendor requires subservice permissioning, a code must be provided
with each data item from that vendor. This entitlement code is used by the
permissioning system (DACS) to control access to data.
Enumerated Type An enumerated type is one of the field types defined for Marketfeed. It con-
sists of a set of mnemonics, each having its own specific meaning. A dis-
playable string is associated with each of these mnemonics.
Enumerated Value The integer value equivalent of data that has an enumerated type.
ETIC Entitlements TIC. Entitlements TIC provides the entitlement profile
needed for a TIB publisher and subscriber.
Expanded Value The full mnemonic string for data that has an enumerated type.
Fading An ANSI extension that many users and sources require, where an area of
updated text must be highlighted for a short time to draw attention to it.
After the end of the fade period, the text returns to its original color. Appli-
cations implement fading as follows: when a character is changed, it is
displayed initially with the “Fading” set of attributes; after a fixed period of
time, it is re-displayed with the default attributes.

SFC Developer’s Guide 340


APPENDIX A: GLOSSARY

FID Applies to record data as defined by Marketfeed. A Field Identifier (FID) is


an integer that identifies a [Service, Field Name] pair. This integer is
unique within a given RMDS or Triarch system.
FID Database The repository of all valid market data FIDs. On Triarch or RMDS, this is
generated from the appendix_a file. On Rendezvous, this can be read
from a series of configuration files or can be downloaded from the TIC.
Also referred to as the data dictionary.
Field As applied to records, a field is a constituent component of record data as
defined by Marketfeed.
Field List Number See Record Template Number.
Field Name Applies to record data as defined by Marketfeed. This is the name given to
a component field of record data (e.g., BID, ASK). Such names are unique
across a service.
Field Type Applies to record data as defined by Marketfeed. The name given to the
type of data carried in a given field of record data (e.g., INTEGER, PRICE).
Full-Cache Service A publishing service that pre-loads all available records into its cache. See
also Non-Interactive Service, Source-Driven.
IDN The Reuters Integrated Data Network (IDN) combines multiple sources of
information into a single format. IDN is characterized by record data and
high transmission speed.
Image The complete representation of a market data item. All of the fields that will
ever be in the record have been created.
Inserts Allows a peer-to-peer dialogue between a sink client and a source service.
The dialogue is initiated by the sink client. Insert usage is determined by
the application, although this capability is typically used to add information
to a data stream. Also known as a Contribution.
Interactive Publisher A publisher that can accept dynamic item requests. See also Sink-Driven.

SFC Developer’s Guide 341


APPENDIX A: GLOSSARY

Inactive A market data item is in this state when it is closed or destroyed. Some-
times, the market data infrastructure will force an item to be closed, and
thus become inactive. Inactive is a terminal state. Once an item is inactive,
it cannot become active again.
Item See Market Data Item.
Local Publisher A non-interactive publisher on the Rendezvous distribution network of
RMDS or a TIB market data system.
Logical Data Real-time data distributed across a market data system in a display-inde-
pendent format. By implication, applications can access both the syntax
and semantics of all constituent elements of the data. Implemented as
records on Triarch.
Logical Page A page that has been broken down into regions. Page data and attributes
are available by accessing a row and column.
Marketfeed Originally the Reuters presentation protocol providing public access to
data supplied by Reuters. Its purpose is to support the transfer of data
between Reuters and user computer systems in a consistent and logical
format for Triarch or RMDS.
Market Data Hub The set of components that provide resilient and scalable integration of the
RMDS with external sources of real-time market data and news. The hub
is comprised of the information source, source distributors, and compatible
feed handlers.
Market Data Item Information from a specified source (e.g., IDN_SELECTFEED or
YOUR_SOURCE) for a specified item (e.g., DEM=). Market data items are
identified by the name of the source service which supplies them and the
name of the individual item within that source service.
MDDS Market Data Distribution System
Node A device connected to a network cable. This usually refers to a server or a
workstation.

SFC Developer’s Guide 342


APPENDIX A: GLOSSARY

Non-Interactive Pub- A publisher that cannot except dynamic requests for market data items
lisher that it does not know about. See also Full-Cache Service, Source-
Driven.
Page A page is a type of data item formatted for distribution to display systems.
The data includes attribute information.
Page Attributes Information that describes how a page’s text should be displayed; e.g.
properties such as highlighting, blinking, color, etc.
Page Record A logical record that contain rows of text. Page records are different than
pages because page records do not contain attribute information. They are
also delivered from record sources. An example is an IDN Page Record.
Page Source A source that supplies data items in the form of pages. Pages are of vari-
able dimensions, but typically displayed in 80 columns and 24 or 25 rows.
Permissionable Entity A numeric code included in each Reuters IDN record. The PE is used to
(PE) determine to which subservice(s) the record belongs. For example the PE
value 62 indicates that the item is from the New York Stock Exchange.
Publisher An application that creates market data items and distributes them to a
market data infrastructure. Publishers can manage the state and update
the values of the market data items. In contrast, contributions do not have
a state model.
Record A record is a type of data item encoded in a form that is convenient for use
by computer applications.
Record Source A source that supplies data items in the form of records.
Record Template A specification of all of the fields that are in a record.
Record Template Num- The number that specifies which record template was used to create the
ber record of a given type. Also called Field List Number.
Rendezvous See TIBCO Rendezvous.
RIC Reuters Instrument Code. A RIC is a unique identifier for a record.

SFC Developer’s Guide 343


APPENDIX A: GLOSSARY

RMDS Reuters Market Data System. The market data system that fully leverages
the TSA Framework and consists of a best-of-breed combination of Triarch
and the TIB MDDS.
RRCP Reuters Reliable Communication Protocol. The UDP broadcast-based
communications layer of RRDP.
RRDP Reuters Reliable Datagram Protocol. A stack of protocols used to commu-
nicate between the key processes which make up the Triarch backbone or
the Reuters Market Data Hub. RRDP consists of RRMP and RRCP.
RRMP Reuters Reliable Messaging Protocol. The session management layer of
RRDP.
RTIC TIC—RMDS Edition. The RMDS caching server that connects a Reuters
Market Data Hub with a Rendezvous Distribution Layer.
RV See TIBCO Rendezvous.
RVD Rendezvous Daemon. RVD is a process that listens to multicast traffic on
a Rendezvous network. SFC gets data directly from the RVD.
SASS Subject Addressed Subscription Service. The SASS protocol is used by
the TIC and RTIC to deliver market data over Rendezvous network.
SBE Subject Based Entitlements
Server A server is a process or several coordinating processes whose function it
is to satisfy client requests.
Service A logical entity, made up of one or more source applications that have
been configured to provide a single, coherent view of a set of data. Sink
applications request data from services.
Service Distributor (a.k.a. Service Manager) An optional process that implements many of the
advanced information resource management features of an RRDP-based
Market Data Hub. The Service Distributor ensures that requests made by a
Sink Distributor (on Triarch) or an RTIC (on RMDS) are directed to the
most appropriate Source Distributor at the optimum rate.
Sink A consumer of data from the RMDS or Triarch network.

SFC Developer’s Guide 344


APPENDIX A: GLOSSARY

Sink Application An SSL application that functions as a sink client.


Sink Client A consumer of data from the Triarch network which interfaces with a Sink
Distributor via the SSL Library.
Sink Components The underlying SSL components that are specific to a sink client. The sink
components consist of the Sink Distributor and SSL Library.
Sink Distributor The Sink Distributor is a daemon process that accepts user requests and
delivers data items to the sink clients which it serves.
Source A contributor of data items to the RMDS or Triarch network.
Sink-Driven Source A source whose cache is determined, within the limitations of the applica-
tion, by demand from consuming applications. At any given point in time,
the cache of the source client contains a subset of all possible items avail-
able from that source client. Also known as a selective source or interac-
tive source.
Source-Driven Source A source client whose cache is determined by the source client itself.
Demand from the network will not change the contents of a source-driven
source client’s cache. At any given point in time, the cache of the source
client contains all possible items available from that source client. Also
known as a full cache source or non-interactive source.
Source Application An SSL application that functions as a source client.
Source Components The underlying SSL components that are specific to a source client. These
components are the Source Distributor and SSL Library.
Source Distributor The Source Distributor is a daemon process which is used to distribute
data items to the RMDS or Triarch network.
Source Server A logical entity that consists of a source client and source distributor.
Source service most commonly integrate datafeeds from vendors,
exchanges, etc. with an RMDS or Triarch network. The source server sup-
plies items upon request and forwards updates to these items as they are
received.

SFC Developer’s Guide 345


APPENDIX A: GLOSSARY

Source Service The name by which a particular vendor or data contributor is identified on
the Triarch network. A source service is comprised of one or more source
servers on the Triarch network.
SSL Source-Sink Library. A Reuters software product that provides an applica-
tion programming interface to the Triarch network. “SSL” is also used
when referring to the Triarch implementation of SFC.
System Foundation A set of object oriented class libraries written in C++. The SFC includes a
Classes (SFC) series of abstract interfaces and implementations to enable easy and con-
sistent access to both real-time and historical data.
Stale A state indicating that a service is unavailable or a market data item may
not have the current value. This state could result from mis-configuration,
network problems, or failures of upstream market data components.
State For a given application, each channel and data stream may be in one of
several possible defined states (e.g., open data stale). Certain events
cause a transition from one state to another.
Status A status indicates the state of a data item. For example, a status may indi-
cate that the item is unavailable, that the data provided may not be com-
plete, or that the item is now up to date.
Subscriber An application that listens for market data events. See also Consumer,
Client Application, Sink Client.
Triarch A network infrastructure aimed at the financial market place. It is designed
to distribute market data in an efficient manner. Core distribution compo-
nents of Triarch are the Source, Service, and Sink Distributors.
TIB The Information Bus. “TIB” is used when referring to the Rendezvous
implementation of SFC. It is also sometimes used to refer to the TIC-based
TIB infrastructure.
TIBCO The Information Bus Company
TIBCO Rendezvous A broadcast-based message delivery system that can be used to deliver
market data. The TIB implementation of SFC uses the Rendezvous infra-
structure.

SFC Developer’s Guide 346


APPENDIX A: GLOSSARY

TIC TIBCO Information Cache. The caching server that connects a TIB ciSer-
ver feed network with a ciServer or Rendezvous-based client-delivery net-
work. It caches market data broadcast traffic so it can provide initial
images to client applications. The TIC is the caching component of the TIB
infrastructure.
Update An update is a modification to the contents of a data item. A source sends
updates asynchronously as the contents of the item change.

SFC Developer’s Guide 347


APPENDIX B: TRIARCH INFRASTRUCTURE
B.1 Overview
Reuters has created the SSL architecture in order to connect suppliers and consumers of financial
information. From an application programmer’s perspective, the SSL may be thought of as an
architecture for building location-independent applications. In such an environment, applications can
distribute both data and functionality across one or more cooperating machines at one or more
geographic locations. Such an environment allows users to transparently make use of the combined
computing resources that are provided by a distributed system—such as redundancy and fault-
tolerance, load balancing, normalization, and integration of internal and external data or services—
while adhering to a consistent real-time client/server model.

B.2 The SSL Interface


User applications interface with the SSL infrastructure using a variety of logical constructs. This
section describes the entities used by an application to communicate with the SSL in order to request
network data and to receive information about the state of the network or data.
In order for these communication processes to occur, the sink, source, or message application must
first mount a channel.

(SSL) Channel A channel connects the sink application to the sink distributor . Multiple
channels may be mounted, and each channel is independent of any other
channel.
Most of the function calls, and all of the events that are available via the
SSL API, require that the application specify or provide a channel number
to the application letting it know to which connection an event applies.

For sink application programming, it also important to understand the concept of a data stream.

Data Stream A data stream is opened for a data item, allowing information about that
item to flow across a channel. The data stream logically relates a channel,
service name, and item name. An open data stream contains an image
message followed by any number of updates and state information. Infor-
mation concerning the state of the data is guaranteed to be sent, whether
the state is OK, STALE, or CLOSED.

SFC Developer’s Guide 348


APPENDIX B: TRIARCH INFRASTRUCTURE

In order to receive a data item, a sink application must open a data stream for that item. Likewise, a
source application sends an item to the network through an open data stream. Multiple data streams
may be opened on a channel, but only one data stream can be opened for a particular item on one
channel. If multiple channels are mounted, one data stream may be opened for the same data item on
each of the channels.
Once a channel has been mounted by a sink application, the sink application can request data items.
It is important to understand that the response to a sink application's request for a data item is not a
single, discrete event, but instead is a continual stream of data events (see Figures B.1 and B.2). As
the market changes throughout the day, the original data will be updated (as long as the source
remains active and the application is connected). Status messages and (in some cases) new images
will be sent if the data becomes stale. Data and status information will continue to flow through the
stream, as it is available, until the data stream is closed.

Source Source
Application Distributor
Update Status Update Image

Data Stream for Channel 1, IDN_SELECTFEED, DEM=

Figure B.1: Source Data Stream

Sink Sink
Distributor Application
Update Status Update Image

Data Stream for Channel 1, IDN_SELECTFEED, DEM=

Figure B.2: Sink Data Stream

SFC Developer’s Guide 349


APPENDIX B: TRIARCH INFRASTRUCTURE

B.3 SSL Sink Components

B.3.1 The Sink Application


Sink applications request information from (see Figure B.3). If the information is already being held by
the , it is provided to the application. If the information is not currently available in the infrastructure, it
is requested from the .

Application
Reuters Reuters Source
Server A Server B Service SSL
Source Source Source
Distributor Distributor Distributor

Network Backbone

Sink
Distributor

ATW
PTW

Figure B.3: Typical Components of a Simple Network

Unless a “snapshot” request is made by the sink application requesting the data, the request is for a
data stream to be opened to the service. Assuming that the request is for an actual data item and any
permission checks have been satisfied, the service will provide an image of the current contents of the
data item. As the data in the item changes, updates will be provided to the sink application until it
indicates that it is no longer interested in the data item, by closing the data stream.

SFC Developer’s Guide 350


APPENDIX B: TRIARCH INFRASTRUCTURE

B.3.2 Sink Distributor


The SSL Sink Distributor is responsible for responding to sink requests, maintaining communications
with the required source services, and distributing SSL messages received from a source service to
the proper sink clients. A sink application connects to a Sink Distributor through the use of the common
software routines in the SSL Library. Architecturally, the Sink Distributor may reside on the same node
as the sink client or on a separate node, in which case they communicate over the network.
The relationship between a Sink Distributor and an application is shown in Figure B.4.

Network Backbone

Sink
Distributor

IPC

SSL Library

Requests Responses returned


sent for Sink
Application via SSL events
data items

Figure B.4: SSL Sink Components

A sink application accesses through its connection to the Sink Distributor. It is the role of the Sink
Distributor to retrieve data items and forward updates on behalf of the sink application. The Sink
Distributor communicates by passing messages using a socket Interprocess Communication (IPC)
mechanism. This allows great configuration flexibility, since these components may reside on any
node on the network.

SFC Developer’s Guide 351


APPENDIX B: TRIARCH INFRASTRUCTURE

B.4 Design Goals and System Features

B.4.1 Triarch System Design Goals


The Triarch Infrastructure has been designed to distribute information, with the following key goals in
mind:
• Reliable Data Communications
• Flexibility and Scalability
• Platform Independence
• Optimal Resource Usage
• Fault-Tolerance and Resiliency
• Single Item Open Request
• Monitoring of Status and Component Health
• Data Access Control
The requirements driven by these goals are described in the following paragraphs in order to enhance
the user’s understanding of the intended role of Triarch.

B.4.2 Reliable Data Communications


In a financial environment, the timeliness and accuracy of information delivery is key. Data must be
delivered quickly, and often this data must be sent to multiple users or applications. Knowing and
managing the state of data in a financial network is important. In this environment it is mandatory to
inform users of stale or lost data.
In order to ensure the maximum efficiency and reliability of data, Triarch makes use of a combination
of standard TCP/IP virtual circuits and a specially developed reliable broadcast communication
scheme, based on the Reuters Reliable Datagram Protocol (RRDP). The RRDP protocol is used to
communicate between the key backbone processes which make up the Triarch Infrastructure. RRDP
ensures rapid and reliable delivery of data to multiple nodes, providing packet sequencing, negative
acknowledgment, bitmap filtering, and keep-alive messaging between components. The underlying
communication protocol is transparent to the application user, and is simplified for the application
developer who needs to interact with only the software library—a set of software routines that handle
the common communication interactions with the Triarch network.

SFC Developer’s Guide 352


APPENDIX B: TRIARCH INFRASTRUCTURE

B.4.3 Flexibility and Scalability


The Triarch Infrastructure has been designed to provide the following aspects of flexibility and
scalability:
• Flexible support of differing types of data
Triarch supports both well-defined normalized data types and fully user-definable data types.
These user-defined types are integrated with well-defined market data types to allow for the
introduction of new data and data types without major system administration or programming
overhead.
• Scalability from small to large numbers of users
The network is scalable to permit efficient operation for variable numbers of users and
applications. It is possible to create Triarch-based solutions which vary between the extremes of
simple systems using a small subset of Triarch features and products, to large and complex
integrated systems. These Triarch solutions can also be provided for a variety of network
topologies, with the hierarchical nature of the system components permitting easy scalability.
• Support for a large set of off-the-shelf data sources
In excess of 30 different feed handlers are available for Triarch, including source servers to
access digital information from Reuters, Telerate, Knight-Ridder, as well as many direct stock
exchange and Inter Dealer Broker (IDB) feeds. Handlers, working in conjunction with a Data
Contribution Server (DCS), are also available to contribute data back to information vendors.
• Flexibility in the choice of underlying system platforms - through open system design
The Triarch system has been built to be fully distributed using the principles of open system
design. As few assumptions as possible are made about the environment in which the distribution
software and library routines run. The use of TCP/IP communication protocols allows for great
flexibility in physical network implementation. Many types of network have been used as the basis
of Triarch solutions, including, Ethernet (e.g., 10base2, 10baseT), Token Ring, ATM, and wide-
area links. The protocols and data formats used are such that machines of different types and
architectures can communicate and be used interchangeably. Workstation types based on
different hardware platforms and operating systems can be mixed freely.

B.4.4 Optimal Resource Usage


The underlying Triarch software has been designed to effectively manage complex and expensive data
resources (i.e., those provided by vendor datafeeds). Where multiple source servers are providing a

SFC Developer’s Guide 353


APPENDIX B: TRIARCH INFRASTRUCTURE

single service, the system has been designed to provide redundancy as well as to optimize server
usage in normal operating circumstances. Optimized management is key when datafeeds provide a
complex set of constraints like data storage limitations, data request (or throttle) limitations, or mixed
delivery mechanisms.
Several key features are available for resource optimization:
• Optimized Resource Management
Multiple instances of a source server appear as a single service to the users, making the
optimization transparent. Where multiple instances of a server are present, the system strives to
ensure that any given item should be supplied by only a single server. All the available data item
storage (called “cache”) slots will be used before new item requests force items to be removed
from storage. When the resources are strictly limited, managed data storage removal (called
“preemption”) is available.
A powerful scheme allows the use of priorities to determine the best candidate to be preempted
from the cache to make way for a new request. The priority scheme supports various features
including the locking of cache items and allowing unconditional candidates for preemption.
Automatic re-request management enables the system, rather than the user, to manage request
retries. Control is asserted during times of insufficient resources, and server failure or failover is
managed gracefully.
• Optimum Response Timing
Requests for data items are managed intelligently. If any source server is already supplying an
item stored in its cache, a new request for that item will be fulfilled automatically from that server.
If multiple items are requested at once and the data is available on multiple servers, the requests
are grouped and sent to different servers for processing in parallel.
• Request Throttling
A source server can indicate that it is temporarily unable to service requests, i.e., it is throttled”, in
order to avoid server overload. The server may also indicate the optimum queue size that it is
willing to accept.

B.4.5 Fault Tolerance and Resiliency


Fault-tolerant operating procedures are mandatory in a mission-critical information distribution system.
In the Triarch software, a series of measures are implemented to ensure that backup resources can
automatically take the place of operational servers in case of failure. When multiple source servers are

SFC Developer’s Guide 354


APPENDIX B: TRIARCH INFRASTRUCTURE

used to implement a single service and an individual server fails, the system automatically recovers
failed items while sharing the load equally among the remaining servers.

B.4.6 Single Item Open Request


When a sink application opens an item, it remains open until:
• closed by the sink application, or
• closed by the source application or infrastructure with a code indicating that the item is in a non-
recoverable state.
If the source application closes an item but indicates that it might be recoverable, the SSL
Infrastructure automatically tries to recall the item. A timer-driven retry queue is used for items that
cannot be recovered immediately (due to resource shortage or a source problem). The SSL
Infrastructure does everything possible to provide data for an open item.
The single open strategy helps to utilize system resources more efficiently and frees sink application
developers from having to implement re-request strategies.

B.4.7 Management and Monitoring of Status


Tools are available to monitor the main processing components of Triarch. The Network Management
Agent reports operational statistics through the use of the Simple Network Management Protocol
(SNMP).

B.4.8 Data Access Control


Data permissioning and entitlement is enforced using DACS which allows Triarch system
administrators to control access rights to information on the network.

B.5 Request Routing and Resource Optimization


To provide a better understanding of how Triarch operates, this section describes how requests are
routed to servers.
As far as the sink application is concerned, a request is placed using the SSL Library. The library, in
turn, communicates over a TCP virtual circuit with the Sink Distributor. The Sink Distributor masks the
fact that two or more datafeeds or source servers from a single information vendor may be required
due to heavy trader demand or to ensure redundancy. Thus, the sink application sees a single logical

SFC Developer’s Guide 355


APPENDIX B: TRIARCH INFRASTRUCTURE

service. For example, if a Triarch system is configured with two Selectservers, a sink application can
determine that the Selectserver service is available, but the sink application is unable to distinguish the
actual number of servers.
Figure B.5 shows a typical configuration used in network request routing where (N) source servers of
the same type are present on the network. All of these source servers appear as a single service on
the network. Each may support a single datafeed or several datafeeds.

Datafeed of Datafeed of
Type A Type A

Source Source SERVICE A


...
Server A(1) Server A(N)

Network Backbone

Sink(s)

Figure B.5: Request Routing Configuration

In SSL 4.x, an optional process (the Service Distributor) performs resource management. Because the
Service Distributor is optional, two scenarios exist for request routing:
• Request routing among source servers without the presence of a Service Distributor
• Request routing among source servers when the Service Distributor is present
In either case, the SSL Infrastructure:
• Ensures that all available source servers or datafeeds share the load of responding to requests
for data from Triarch users.
• Ensures that if a copy of a given data item is already available on Triarch, then subsequent
requests for the same item are satisfied from this copy, rather than by re-requesting the item from

SFC Developer’s Guide 356


APPENDIX B: TRIARCH INFRASTRUCTURE

another datafeed. This avoids so-called cache duplication, where the same item is open
simultaneously on several datafeeds.

B.5.1 Basic Request Routing without the Optional Service Distributor


Request routing without the Service Distributor provides reasonable load leveling performance without
the need to allocate resources to an additional distributor.
Multiple mechanisms are used to achieve this. All servers periodically broadcast a load level that tells
sinks how heavily loaded they are. The algorithm used to calculate this load level is determined by the
particular source service. For some types of services, the most critical resource may be available
communications bandwidth to the information provider; for others, it may be processor power.
If a sink application makes a retrieval request, the Sink Distributor does the following:
• If the service type is source-driven, the Sink Distributor requests the item from an appropriate
source server.
• If the service type is sink-driven, then a special type of request message is sent to each
available source server. This message requests that the server respond with an image only if it is
available in its cache. If none responds with an image, a regular request is sent to the appropriate
source server.
The Sink Distributor’s requests for data items are routed equally to all source servers until one or more
source servers reaches a predefined threshold limit. Since the source servers are sent requests in
parallel, the cache for all source servers will be used at a fairly equal rate.
After one or more source servers has reached the service threshold, requests are routed equally to all
servers not at threshold. This process of filling source servers in parallel continues until all of the
servers have reached their threshold. Capacity at threshold does not mean that a server is full, but that
it is almost full. Once all source servers reach threshold, the requests are routed to the least loaded
servers. When all servers are full, lower priority data items are picked for preemption from source
server cache.
If the datafeed line fails, the source server marks its items as being stale and monitors the datafeed
line. This allows each Sink Distributor to re-request the items previously supported by the failed source
from the remaining available source servers. When the failed line becomes active, the source server
announces that it is back on the network.

SFC Developer’s Guide 357


APPENDIX B: TRIARCH INFRASTRUCTURE

B.5.2 Full Resource Management and Request Routing with the


Service Distributor
The Service Distributor implements many of the advanced information resource management features
of SSL 4.0. It is capable of running on the same node as other components, but will typically be run on
its own dedicated node. A single Service Distributor is capable of managing multiple services at the
same time. It ensures that requests made by a Sink Distributor are directed to the most appropriate
Source Distributor at the optimal rate.
The Service Distributor is an internal piece of the SSL Infrastructure and is not directly accessed by
application software. This optional piece of Triarch is designed to reduce network message traffic,
provide better request routing among source applications within services, and manage global service
preemption. It is increasingly effective as the number of Sink Distributors and the number of source
servers that make up a service increase.
The Service Distributor provides the following added benefits for any services that it manages:
• The Service Distributor ensures that requests from a Sink Distributor are directed to the optimal
Source Distributor. No polling of servers is required to locate cached items. The Service
Distributor has knowledge of all open cache slots and uses this knowledge to efficiently route
requests and to manage preemption of data from cache.
• When necessary, the Service Distributor leads the recovery process for a failed source server
based on its knowledge of where items watched by all of the Sink Distributors on the network are
cached. (Refer to the SSL 4.0 Architecture Overview for more information about this feature.)
When the Service Distributor is operating, request traffic is directed from the Sink Distributor to the
Service Distributor (for applicable services). Using the information it maintains on the cache list for
each managed source server and the ability of each server to service requests, the Service Distributor
is able to direct these requests to the optimal Source Distributor. Responses to these requests, and
subsequent updates, flow directly to the requesting Sink Distributor.
When the Service Distributor is restarted after a failure or interruption, it automatically downloads the
necessary information from the Source and Sink Distributors to enable it to restore full information
resource management without manual intervention.
In Figure B.6, requests are routed through the Service Distributor. Responses are sent back to the
requesting application.

SFC Developer’s Guide 358


APPENDIX B: TRIARCH INFRASTRUCTURE

Datafeed Datafeed

Source Service Source


Server Distributor Server

Request Routing
Sink Response Routing
Distributor

Application

Figure B.6: Service Distributor Resource Management

B.5.3 System Resiliency (“Failover”)


Resilience is a system property which minimizes disruption of service in the event of a system failure.
A resilient aspect of the Triarch network is its ability to share the load carried by a datafeed among
other available datafeeds of the same type. When a source server goes down, capacity is absorbed by
the remaining servers of the same type on the network. The server loss has little effect on applications
through the complete use of available Triarch facilities. In addition, resilience is enhanced by the
functionality provided for request routing.
If one of the source servers fails, the system informs user applications on an item-by-item basis that
service has been interrupted. The system will try to retrieve the data from other sources within the
service, and will maintain the stale state of such data until the data is retrieved from another server or
the original server is back up.
When a failed source server recovers or when a new server is added, the system automatically
registers this action. As servers or services are added to or removed from the network, the SSL

SFC Developer’s Guide 359


APPENDIX B: TRIARCH INFRASTRUCTURE

Infrastructure tracks this activity. The system is dynamic; i.e., a new workstation may be added without
restarting the system. When an additional source server of an existing type is added to the network,
the network protocol ensures that all workstations are automatically able to access it. When a new
service is added to the network, the protocol ensures that workstations are informed.
The network protocol suite supports “Keep Alive” messages from both sources and sinks. These
messages, which are sent out at regular intervals, are used to detect the presence and absence of
network nodes. Keep Alive messages are particularly important for source servers. Sinks, and the
Service Distributor when active, receive these messages from all active sources and use this
information in deciding where to address requests for data items.
If a source fails, the Keep Alive messages from that server are no longer seen by the sinks. After the
absence of several such messages, a sink presumes that the server has failed, and any data from the
failed source is immediately marked as stale. If another source server can provide this data, the data
will be retrieved from it. Otherwise, the system places the items in an automatic recovery queue and
maintains the stale status of this data until the source recovers or the application is no longer
interested in the data. The sinks stop sending requests to a failed source until that source server has
recovered and again sends Keep Alive messages.

NOTE: The length of time a sink (or source) will wait before assuming failure of a node is a config-
urable parameter. This time interval should be kept fairly short to ensure that any data that has
recently become stale is not presumed to be valid.

SFC Developer’s Guide 360


APPENDIX B: TRIARCH INFRASTRUCTURE

B.6 SSL Library Configuration

B.6.1 Overview
The SSL Library configuration file provides a centralized configuration database functionality for all
SSL applications. This allows for consistent SSL Library behavior across many interrelated nodes and
applications. In addition, tuning and troubleshooting of SSL applications may be performed without
program recompilation. The SSL Library configuration file consists of a number of configuration
variable settings which may be specified on a per installation, per hosts, or per application name basis.

B.6.2 File Entry Rules and Formats

B.6.2.1 Location of the File


The location of the SSL Library configuration file is determined by the value of the SSLAPI_CONFIG
environment variable or the \HKEY_LOCAL_MACHINE\Software\Reuters\SSL\SSLAPI_CONFIG
registry entry. These variables can be used to point the ssl api configuration to the same file that the
SFC application is using for configuration. If a sslapi.cnf file exists in the current directory, it will always
be used instead of the configured file. If the sslapi.cnf file does not exist, the ipcroute file will be
located per SSL 4.0 guidelines.

B.6.2.2 Special Configuration File Entry Characters


The configuration file uses the # (hash mark) character as the comment character. A commented line
must have the # character as the first non-white-space character on the line.
Each entry in the configuration file contains two fields separated by the ‘:’ character. The first field is
the parameter specification and the second field is the parameter value. The syntax of a database
entry is defined below.

B.6.2.3 Configuration File Entry Format


The configuration file entry format is as follows:
<ClientHost>.<AppInstanceID>.<AppName>.<SSLVersion>.<ParamName>:<ParamValue>
where:

SFC Developer’s Guide 361


APPENDIX B: TRIARCH INFRASTRUCTURE

ClientHost is the name of the machine where the application that requests con-
nection to the SSL Library will run.
AppName is a string which identifies the SSL application on the machine.
AppInstanceID is used to uniquely identify an instance of an application with a spe-
cific AppName on the specific ClientHost.
SSLVersion is used to restrict the version number of the SSL Library to which the
entry applies. For SSL Library version 4.5, specify “SSLAPI_V45” .
ParamName is the name of the configuration variable.

CAUTION: Do not put any whitespace between the parameter name


and the colon that follows it. If whitespace is found, the parameter will
not be recognized and, thus, will be ignored.
ParamValue is a string which is the value assigned to the ParamName.

B.6.2.4 Binding of Configuration Entries


Entries in the SSL Library configuration file can be bound together in two ways:
• tightly with a . (dot) character, or
• loosely with an * (asterisk) character.
A tight binding signifies that the qualifiers on either side of the binding must be sequential (i.e., in the
order specified). An entry with a loose binding begins with an *. The loose binding works as a wildcard
enabling zero or more unspecified qualifiers between the loosely bound qualifiers. Loose bindings
serve the purpose of allowing matching of several possible entries and will still match if the entries
change within the wildcarded section.
For example, the following entry sets event logging file size to 5000 bytes for all SSL applications:
*eventLogging:5000
However, if applications running on node test1 require a larger file size, the following can be
specified:

SFC Developer’s Guide 362


APPENDIX B: TRIARCH INFRASTRUCTURE

test1*eventLogging:20000

B.6.2.5 Order of Precedence


The SSL Library configuration file need not contain a specification for every available parameter. The
Library has built-in default values for all parameters. If a parameter specification is omitted from the
configuration file, the corresponding default takes effect.
An SSL application may choose to override a value specified in the configuration file at run time. This
can be done by setting a mount option or via an sslSetProperty() function call, but only for those
configuration parameters which have a corresponding SSL_ property.
The SSL Library determines the value of every configuration variable by the following order of
precedence:

Run-time Configuration SSL Library


property file setting default
setting

B.6.2.6 Updating the Configuration File


In addition to run-time property setting, the SSL Library allows updates to the configuration file to take
affect without restarting the application. This is accomplished by retrieving parameter values in the
course of executing appropriate SSL function calls. For example, the numBuffers parameter is
examined every time an sslSnkMount() call is issued or when a session reconnection attempt is
made.

B.6.3 Valid Configuration File Parameters

B.6.3.1 eventLogging

Default Value: 10000 (bytes)


Related Property: SSL_OPT_LOG_EVENT_FAIL
Becomes Effective: sslQueryInterface() call

SFC Developer’s Guide 363


APPENDIX B: TRIARCH INFRASTRUCTURE

Parameter Function: Automatically enables the logging of event handling failures with a
specified file size. The name of the log file is SSL_elog<pid>, where
<pid> is a unique numeric process ID assigned by the operating sys-
tem.

B.6.3.2 functionLogging

Default Value: 10000 (bytes)


Related Property: sslErrorLog() call
Becomes Effective: sslQueryInterface() call
Parameter Function: Automatically enables function call error logging with a specified file
size. The name of the log file is SSL_elog<pid>, where <pid> is a
unique numeric process ID assigned by the operating system.

B.6.3.3 ipcConnectionTimeout

Default Value: 10 (seconds)


Related Property: None
Becomes Effective: sslSnkMount() call
Parameter Function: Controls the amount of time the sslSnkMount() call is allowed to take
when making a connection to a source application.

B.6.3.4 ipcRoute

Default Value: Source application: Not Used


Sink application: triarch_sink localhost
Related Property: None
Becomes Effective: sslSnkMount() or sslMsgMount() call

SFC Developer’s Guide 364


APPENDIX B: TRIARCH INFRASTRUCTURE

Parameter Function: Allows specification of the SSL IPC server and host name pair.

Syntax 1:
*ipcRoute: ipcService [hostname...]

Syntax 2:
*name1.ipcRoute: ipcService [hostname1...]
*name2.ipcRoute: ipcService [hostname2...]
...
Syntax 1 specifies the TCP service port and host to which a sink
application will be connected when no value is set for
SSL_SNK_MO_IPC_ROUTE_NAME as part of sslSnkMount().

Syntax 2 allows the sink application to control which port/host it will be


connected to when SSL_SNK_MO_IPC_ROUTE_NAME is set to
name1 or name2, etc.

Syntax 2 is also used when SSL_SNK_MO_IPC_ROUTE_NAME is


not specified on the mount call but instead the ipcRouteName
parameter is present. By scoping multiple ipcRouteName entries, a
single configuration file can be used by multiple machines to steer
each one’s mount requests to a different source host (or port).

Multiple host names may be specified in order to configure redundant


source applications. The default hostname is “localhost”. The default
ipcService is “triarch_sink”. The ipcService must also be defined in
the TCP/IP service definition file (e.g. /etc/services). This parameter
is not used by source applications.

B.6.3.5 ipcRouteName

Default Value: None


Related Property: Mount option
Becomes Effective: sslSnkMount() or sslMsgMount() call

SFC Developer’s Guide 365


APPENDIX B: TRIARCH INFRASTRUCTURE

Parameter Function: Controls which ipcRoute entry will be used by sink applications that
do not specify an SSL_SNK_MO_IPC_ROUTE_NAME value with
sslSnkMount(). Only useful if multiple named ipcRoute entries are
present. If SSL_SNK_MO_IPC_ROUTE_NAME is specified, that
value overrides this parameter. This parameter is not used by source
applications. See ipcRoute for more information.

B.6.3.6 ipcServer

Default Value: None


Related Property: The IPCServerName argument to the sslSrcMount() call or the
SSL_OPT_IPC_SERVER_NAME property.
Becomes Effective: sslSrcMount() call
Parameter Function: Allows specification of the name of the SSL IPC service provided by
the source application. The ipcServer must also be defined in the
TCP/IP service definition file (e.g. /etc/services). This parameter is
not used by sink or message applications.

B.6.3.7 maxMounts

Default Value: 4 less than the per-process file descriptor limit set by the operating
system
Related Property: SSL_SRC_MAX_SESSIONS
Becomes Effective: sslSrcMount() call
Parameter Function: Controls the maximum number of sessions supported by a single
source channel.

SFC Developer’s Guide 366


APPENDIX B: TRIARCH INFRASTRUCTURE

B.6.3.8 maxProcessBuffers

Default Value: 1048576


Related Property: None
Becomes Effective: sslQueryInterface() call
Parameter Function: Controls the maximum number of 3300-byte message buffers that
can be dynamically allocated for a single process for its buffer pool.
Buffers from the pool are shared between channels up to this per-pro-
cess limit.

B.6.3.9 maxRemountDelay

Default Value: 30 (seconds)


Related Property: SSL_SNK_MAX_RETRY_DELAY
Becomes Effective: sslSnkMount() call or successful channel recovery
Parameter Function: Controls the maximum delay between channel reconnection
attempts.

B.6.3.10 maxUnconfirmedMsgs

Default Value: 10
Related Property: SSL_OPT_MAX_UNCONFIRMED_MSG_COUNT
Becomes Effective: SSL_ET_SESSION_ACCEPTED event and sslSnkMount() call
Parameter Function: Controls the setting of the preferred number of unconfirmed IPC mes-
sages.

SFC Developer’s Guide 367


APPENDIX B: TRIARCH INFRASTRUCTURE

B.6.3.11 messageTracing

Default Value: 10000 (bytes)


Related Property: None
Becomes Effective: sslQueryInterface() call
Parameter Function: Automatically enables IPC message tracing with the specified file
size. The name of the log file is IPCTRACE<pid>, where <pid> is a
unique numeric process ID assigned by the operating system.

B.6.3.12 messageTracingFlags

Default Value: None


Related Property: None
Becomes Effective: sslQueryInterface() call
Parameter Function: Controls the granularity of message formatting in the message trace
file. Any or all of the following valid flags may be specified:
SSL_TRACE_IN — Trace inbound messages.
SSL_TRACE_OUT — Trace outbound messages.
SSL_TRACE_DATA — Trace data portion of the message.
SSL_TRACE_HEX — Include hex dump of traced data.

B.6.3.13 minRemountDelay

Default Value: 1 (second)


Related Property: SSL_SNK_MIN_RETRY_DELAY
Becomes Effective: sslSrcMount() or successful channel recovery
Parameter Function: Controls the minimum delay between channel reconnection attempts.

SFC Developer’s Guide 368


APPENDIX B: TRIARCH INFRASTRUCTURE

B.6.3.14 msgMountDelimiter

Default Value: “-”


Related Property: Mount option
Becomes Effective: sslMsgMount() call
Parameter Function: Controls the delimiter in the sslMsgOpen() filter string.

B.6.3.15 numInputBuffers

Default Value: 2
Related Property: None
Becomes Effective: SSL_ET_SESSION_ACCEPTED event or sslSnkMount() call
Parameter Function: Controls the number of 3300-byte SSL message input buffers used to
handle and store incoming messages per channel. There must be at
least two input buffers per channel.

B.6.3.16 numOutputBuffers

Default Value: 3000


Related Property: None
Becomes Effective: SSL_ET_SESSION_ACCEPTED event or sslSnkMount() call
Parameter Function: Controls the maximum number of 3300-byte output buffers that can
be used to handle and store outgoing SSL messages per channel.
Two buffers are allocated per SSL channel and additional buffers can
be taken from the dynamic buffer pool up to this per-channel limit.

SFC Developer’s Guide 369


APPENDIX B: TRIARCH INFRASTRUCTURE

B.6.3.17 pingInterval

Default Value: 20 (seconds)


Related Property: SSL_OPT_SESSION_TIMEOUT
Becomes Effective: SSL_ET_SESSION_ACCEPTED event and sslSnkMount() call
Parameter Function: Controls the amount of time that a channel is allowed to remain idle.
Ping messages are sent automatically by the SSL Library to ensure
that the channel remains operational. Session timeout occurs if no
response is received to three consecutive ping messages. (Note that
since the ping interval used is the lesser of the values set for the
source and client applications, in order to increase the timeout from
the default, the value of this parameter must be increased on both
sides.)

The minimum value for pingInterval is 3 seconds.

B.6.3.18 serviceId

Default Value: None


Related Property: None
Becomes Effective: SSL 4.0 session establishment

SFC Developer’s Guide 370


APPENDIX B: TRIARCH INFRASTRUCTURE

Parameter Function: Controls the mapping of service names to numeric service IDs.
Required for every service so that the source application can support
Bandwidth Enhancement capabilities. Used when an SSL 4.0 sink
application is connected to an SSL 4.5 source application and the
sink application requires access locks. This parameter is used to
translate permission data format into access lock format. The servi-
ceId parameter must be specified as a suffix of the string containing
the actual service name; e.g.:
IDN_SELECTFEED.serviceID: 20.
This statement assigns a service ID of 20 to the IDN_SELECTFEED
service.

B.6.3.19 snkResponseThrottle

Default Value: 10 (requests)


Related Property: SSL_SNK_RESPONSE_THROTTLE
Becomes Effective: SSL_ET_SESSION_ACCEPTED event or sslSnkMount() call
Parameter Function: Controls the number of outstanding image requests on a channel. (If
this is set too high, it could cause the SSL channel to be cut.)

B.6.3.20 tcpQuickAck

Default Value: FALSE


Related Property: None
Becomes Effective: sslSnkMount() or sslSrcMount() calls

SFC Developer’s Guide 371


APPENDIX B: TRIARCH INFRASTRUCTURE

Parameter Function: Enable or disable the TCP_QUICKACK socket option from the SSL
configuration file, sslapi.cnf . It is disabled by default and is effective
only on Linux platforms.

If the TCP_QUICKACK socket option is enabled, the ACK packet will


be sent immediately, and the latency spikes problem will be reduced.
However, setting the TCP_QUICKACK socket option might cause a
performance problem on SSL API, and the latency result may vary
across hardware/OS platforms.

B.6.4 Sample Configuration File


The following example illustrates various configuration file parameters:
#
# All apps will try initial connect for 10 seconds
*ipcConnectionTimeout: 10
#
# Default for all sink applications on all hosts
*ipcRoute: ssl_sink richs236
#
# Allow sink applications to specify which RDF to mount to
# by using SSL_SNK_MO_IPC_ROUTE_NAME on the sslSnkMount() call.
*rdf1.ipcRoute: triarch_sink rdfchgwc0102
*rdf2.ipcRoute: triarch_sink rdfchgwc0202
#
# SSL4.5 sink applications on richs256, with a route name of
# “sink_client”,connect to the service named “ssl_sink” on host
# richs128
richs256*SSLAPI_V45.ipcRouteName: sink_client
*sink_client.ipcRoute: ssl_sink richs128
#
# Service ID translation
*IDN_RDF.serviceId: 25
*IDN_SELECTFEED.serviceId: 20
#
# Concurrent source sessions and max unconfirmed messages
*maxMounts: 10
*maxUnconfirmedMsgs: 15

SFC Developer’s Guide 372


APPENDIX B: TRIARCH INFRASTRUCTURE

#
# Session timeout is 3X pingInterval
*pingInterval: 10
*msgMountDelimiter: +
#
# Disable message trace
#*messageTracingFlags: SSL_TRACE_IN SSL_TRACE_OUT SSL_TRACE_DATA SSL_TRACE_HEX
#*messageTracing: 20000
#
# Enable logging
*functionLogging: 20000
*eventLogging: 20000

SFC Developer’s Guide 373


APPENDIX C: TIB INFRASTRUCTURE - SASS2
C.1 Overview
The TIB infrastructure uses the SASS protocol to deliver market data to client applications over a
Rendezvous network. The infrastructure is highly scaleable. It broadcasts updates to take advantage
of a large number of users looking at the same data.
See TIB/Rendezvous Concepts for more information on Rendezvous.

C.2 Architecture
The SFC on TIB enables client applications to either publish data or consume data from a TIB
infrastructure using Rendezvous. A TIC must be used to cache published data. The SASS2 protocol
must be used with the TIB infrastructure. Figure C.1 illustrates the possible deployments that can be
achieved. The following the sections describe the type of deployment that can be interfaced to by the
SFC API.

C.2.1 TIC-based Publish/Subscribe


In a TIC-based publish/subscribe, the data that is published from the publishing application need not
contain a complete set of fields. The intermediate application, the TIC, will cache the image, and
provide delta updates to the client applications. All that needs to be sent are the fields that have
changed.

NOTE: It is necessary that a publisher provide a record template when operating with an SFC client
or the TIC will not cache the data. Record template also must be supplied to support historical Ren-
dezvous based market data products

SFC Developer’s Guide 374


APPENDIX C: TIB INFRASTRUCTURE - SASS2

SFC TIC
Publishing (Cache Process)
Application

Data Flow Data Flow Data Flow

RV Daemon RV Daemon ciServer Daemon

Network Data Flow Data Flow Data Flow

RV Daemon ciServer Daemon

Data Flow Data Flow

SFC RV-Based ciServer-Based


Consumer Consumer
Application Application

Figure C.1: SFC Applications in a TIB Infrastructure

C.2.2 Publishing to Support ciServer Subscribers


In order to support older ciServer-based applications via a TIC, a publishing application must supply a
record template number. This template number allows the TIC to coerce the data into the QForm data
format required by these applications. The record format is used by ciServer-based clients in order to
extract the fields that are in the data. An SFC publisher can publish the record template number in the

SFC Developer’s Guide 375


APPENDIX C: TIB INFRASTRUCTURE - SASS2

REC_TYPE field using the setRecordTemplateNumber(RTRString *) method. See section 5.5.3 for
details.

C.2.3 Configuration
The following things may need to be configured in the TIC configuration file to support the SFC:
1. Communicate via Rendezvous and the SASS2 protocol. (This can be done for both publishing
clients and subscribing clients.)
RV_TRANSPORT_IN TRUE;
RV_TRANSPORT_OUT TRUE;
RV_SASS2_SUPPORT TRUE;

2. If you use the RTRTIBFidDb (which is needed to download the data dictionary from the TIC),
you must configure a TIC to send the data dictionary to clients.
PROVIDE_DATA_DICTIONARY TRUE;
3. If you are publishing to a new service, you must configure a TIC to accept the messages for
that service.
BROADCAST
{
SOURCE “MYSOURCE”;
# ...
}
4. If any of the the following configuration values are specified in the TIC configuration file:
RV2_OUTPUT_SERVICE
RV2_OUTPUT_NETWORK
RV2_OUTPUT_DAEMON
RV2_PUBLISH_SERVICE
RV2_PUBLISH_NETWORK
RV2_PUBLISH_DAEMON
Then SFC publishers will need to include the following configuration in the SFC configuration
file:
TIBDistribution*pingInterval : 0

SFC Developer’s Guide 376


APPENDIX C: TIB INFRASTRUCTURE - SASS2

Also, to download a dictionary for the publisher, a RTRTIBFidDb will need to be created
external to the publishing service, using a different RTRTIBConnection. See section 5.5.4.3 for
an example of the workaround.
Other configuration may be needed depending on your environment and usage.
If TIB Entitlements 4 (ETIC) is configured to send entitlement data on a different multicast channel or
broadcast service port than the data from the TIC, then SFC will need to be configured to use the
global entitlement session. See section 5.5.10 for details on how to set the configuration parameters.
See section 4.8.1.3 for information on how to set the parameters programmatically.

SFC Developer’s Guide 377


APPENDIX D: TIB INFRASTRUCTURE - SASS3
D.1 Overview
The TIB infrastructure can be configured to use the SASS3 protocol, also used by RMDS, to deliver
market data over TIBCO Rendezvous. In a TIB SASS3 infrastructure, the protocol, entitlement system,
and data quality (DQA) mechanisms are the same as RMDS, but the data content is the same as a TIB
network.
See TIBCO Rendezvous Concepts for more information on Rendezvous.

D.2 Architecture
The SFC enables client applications to either publish data or consume data from a TIB SASS3
infrastructure using Rendezvous. The TIC must be version 10.x or later. Figure D.1 illustrates the
possible deployments that can be achieved.

TIC
DACS
Server

RV Daemon

Distribution Layer (TIB/RV)

DACS Daemon
RV Daemon RV Daemon

SFC
SFC TIB-Based
TIB-Based Publisher
Consumer

Figure D.1: SFC Applications in TIB SASS3 Infrastructure

SFC Developer’s Guide 378


APPENDIX D: TIB INFRASTRUCTURE - SASS3

The TIC in Figure D.1 can be replaced with a DTIC. To support a DTIC, the SFC’s service provider
discovery mechanism must be disabled. See section 5.5.6.2 for details. In the rest of this section, DTIC
can be interchanged with TIC.
The following sections describe the type of deployment that can be interfaced to by the SFC API.

D.2.1 TIB-Based Publisher


The TIB record publishing implemenation in SFC can be used to publish locally on the Rendezvous
broadcast network. The TIC must be configured to accept messages for that service. The data is
published in TIBMsg self-describing format using the SASS3 protocol. TIB field definitions are used
(either loaded from the tss_fields.cf files or downloaded from a TIC).

NOTE: It is necessary that a publisher provide a record template when operating with an SFC client
or the TIC will not cache the data. Record template also must be supplied to support historical Ren-
dezvous based market data products

D.2.2 TIB-Based Consumer


The TIB page and record subscription implementations in SFC can be used to request data on the
distributions network. The data could be delivered in TIBMsg self-describing or QForm format. The
data will be using TIB field definitions. As long as field names are used instead of FID numbers, SFC
will hide the data format and semantics from the application, so it does not need to be concerned with
the underlying data format.
Entitlement checking is performed in the consumer application. A DACS sink daemon must be run on
the client to retrieve an entitlement profile from the DACS server.
The field definitions that SFC uses can programmatically be overridden by passing a RTRFidDb into a
service. If this is done, both the source and client applications must be configured the same way so
they can understand the data.

D.3 TMF
The SFC enables client applications to consume data from either a SASS3 TIC or SASS3 TMF in a
TIB infrastructure. A TIC must be set up to publish images and updates separately. The TMF receives
the updates from the TIC, aggregates the updates, and publishes the updates out on the distribution
LAN. Figure D.2 illustrates a possible deployment that can be achieved.

SFC Developer’s Guide 379


APPENDIX D: TIB INFRASTRUCTURE - SASS3

SFC can set TMF connection parameters either with configuration (section 5.5.10.1) or
programmatically (section 4.8.1.3).

TMF TIC
update(in) port: 7505 image port: 7501
update(out) port: 7600 update port: 7505

RV Daemon RV Daemon

Distribution Layer (TIB/RV)

RV Daemon RV Daemon

SFC TMF Subscriber SFC TIC Subscriber


image port: 7501 image port: 7501
update port: 7600 update port: 7505

Figure D.2: SFC Application in TIB SASS3 infrastructure with TMF

D.4 Configuration
The following things may need to be configured to support SFC on your TIB SASS3 infrastructure:
1. Rendezvous and SASS3 must be enabled in the client communication configuration file
(typically tic.cf or dtic.cf).
RV_TRANSPORT_IN TRUE;
RV_TRANSPORT_OUT TRUE;
RV_SASS3_SUPPORT TRUE;

2. If you use the RTRTIBFidDb to download the data dictionary from the network, you must
configure the TIC to send the data dictionary to clients in the tic.cf.

SFC Developer’s Guide 380


APPENDIX D: TIB INFRASTRUCTURE - SASS3

PROVIDE_DATA_DICTIONARY TRUE;

3. If you are publishing to a new service, you must configure tic.cf to accept the messages for
that service.
BROADCAST
{
SOURCE “MYSOURCE”;
# ...
}

4. If any of the the following configuration values are specified in the tic.cf:
RV3_OUTPUT_SERVICE
RV3_OUTPUT_NETWORK
RV3_OUTPUT_DAEMON
RV3_PUBLISH_SERVICE
RV3_PUBLISH_NETWORK
RV3_PUBLISH_DAEMON
then SFC publishers will need to include the following configuration in the SFC configuration
file:
*enablePingSubscription : false
Also, to download a dictionary for the publisher, a RTRTIBFidDb will need to be created
external to the publishing service, using a different RTRTIBConnection. See section 5.5.4.3 for
an example of the workaround.
5. The following configuration variables must be set in TMF’s configuration file:
SUPPORT_SASS3 TRUE
RV_UPDATE_SERVICE # match value from RTIC’s RV3_OUTPUT_SERVICE
RV_UPDATE_NETWORK # match value from RTIC’s RV3_OUTPUT_NETWORK
RV_INITIAL_SERVICE # match value from RTIC’s RV3_SERVICE
RV_INITIAL_NETWORK # match value from RTIC’s RV3_NETWORK
Services must be included in SUBJECTS. For example
SUBJECTS
{
ISFS...;

SFC Developer’s Guide 381


APPENDIX D: TIB INFRASTRUCTURE - SASS3

IDN_RDF...;
}
6. SFC’s updateService and updateNetwork configuration variables must match these values
in the TMF’s configuration file:
RV_OUT_SERVICE
RV_OUT_NETWORK
7. For the TIC to detect when broadcast, local publishers die, the following configuration must be
set:
BC_DQA_MODE TRUE;
FEED_FAIL_TIMEOUT 120; # if a message not received every 120
# seconds stale messages are sent for all items.
This mechanism requires TIC 10.1 or later. The groupId must also be configured in the SFC
publisher. See section 5.5.5.1 for details.
Other configuration may be needed depending on your environment and usage.

SFC Developer’s Guide 382


APPENDIX E: RMDS INFRASTRUCTURE
E.1 Overview
In addition to supporting the Triarch and TIB infrastructures, the SFC implementations in this release
can transparently support the Reuters Market Data System (RMDS) infrastructure. The RMDS
infrastructure combines an RRDP-based Market Data Hub with TIBCO Rendezvous distribution to
trading floor applications.
If the RTIC is configured to support legacy TIB applications, it behaves more like a SASS3 TIC. While
the architecture in this Appendix still applies, for most of the SFC implementation details discussed in
Chapter 5, the application will need to be configurated as if it were deployed on a TIB/SASS3
infrastructure. See Appendix E.4 for details on how to detect if an RTIC is configured to support legacy
TIB applications.
See TIBCO Rendezvous Concepts for more information on Rendezvous.

E.2 Architecture
The SFC enables client applications to either publish data or consume data from an RMDS
infrastructure using Rendezvous. An RTIC must be used to connect RRDP and Rendezvous networks
and to cache published data. Figure E.1 illustrates the possible deployments that can be achieved.

SFC Developer’s Guide 383


APPENDIX E: RMDS INFRASTRUCTURE

SFC
Datafeeds &
SSL-Based
Feed Handlers
Publisher

Source Source Source


Distributor Distributor Distributor

RRDP Market Data Hub

RTIC
DACS
Server

RV Daemon

TSA Distribution Layer (TIB/RV)

DACS Daemon
RV Daemon RV Daemon

SFC
SFC TIB-Based
TIB-Based Publisher
Consumer

Figure E.1: SFC Applications in an RMDS Infrastructure

SFC Developer’s Guide 384


APPENDIX E: RMDS INFRASTRUCTURE

The RTIC in Figure E.1 can be replaced with a DTIC for RMDS (RDTIC). To support an RDTIC, the
SFC’s service provider discovery mechanism must be disabled. See section 5.5.6.2 for details. In the
rest of this section, RDTIC can be interchanged with RTIC.
The following sections describe the type of deployment that can be interfaced to by the SFC API.

E.2.1 SSL-Based Publisher


The SSL record publishing implementation in SFC can be used to publish directly to a Source
Distributor on the RRDP Market Data Hub. The Source Distributor must be configured to connect to
the SFC-based source application. The data is published in Marketfeed format using the SSL protocol.
IDN field definitions are used (loaded from the appendix_a and enumtype.def files using a
RTRFileFidDb).

E.2.2 TIB-Based Publisher


The TIB record publishing implemenation in SFC can be used to publish locally on the Rendezvous
broadcast network. The RTIC must be configured to accept messages for that service. The data is
published in TIBMsg self-describing format using the SASS3 protocol. Triarch field definitions are used
(either loaded from the appendix_a and enumtype.def files or downloaded from a RTIC).

E.2.3 TIB-Based Consumer


The TIB page and record subscription implementations in SFC can be used to request data on the
RMDS distribution network. The data could be delivered in TIBMsg self-describing or Marketfeed
format. The data will be using IDN field definitions. As long as field names are used instead of FID
numbers, SFC will hide the data format and semantics from the application, so it does not need to be
concerned with the underlying data format.
Entitlement checking is performed in the consumer application. A DACS sink daemon must be run on
the client to retrieve an entitlement profile from the DACS server.
The field definitions that SFC uses can programmatically be overridden by passing a RTRFidDb into a
service. If this is done, both the source and client applications must be configured the same way so
they can understand the data.

SFC Developer’s Guide 385


APPENDIX E: RMDS INFRASTRUCTURE

E.3 TMF
The SFC enables client applications to consume data from either an RTIC or TMF in an RMDS
infrastructure. An RTIC must be set up to publish images and updates separately. The TMF receives
the updates from the RTIC, aggregates the updates, and publishes the updates out on the distribution
LAN. Figure E.2 illustrates a possible deployment that can be achieved.
SFC can set TMF connection parameters either with configuration (section 5.5.10.1) or
programmatically (section 4.8.1.3).

SFC Developer’s Guide 386


APPENDIX E: RMDS INFRASTRUCTURE

SFC
Datafeeds &
SSL-Based
Feed Handlers
Publisher

Source Source
Distributor Distributor

RRDP Market Data Hub

TMF RTIC
update(in) port: 7505 image port: 7501
update(out) port: 7600 update port: 7505

RV Daemon RV Daemon

Distribution Layer (TIB/RV)

RV Daemon RV Daemon

SFC TMF Subscriber SFC RTIC Subscriber


image port: 7501 image port: 7501
update port: 7600 update port: 7505

Figure E.2: SFC Applications in RMDS infrastructure with TMF

SFC Developer’s Guide 387


APPENDIX E: RMDS INFRASTRUCTURE

E.4 Configuration
The following things may need to be configured to support SFC on your RMDS infrastructure:
1. Rendezvous and SASS3 must be enabled in the client communication configuration file
(typically rtic.cf or rdtic.cf).
RV_TRANSPORT_IN TRUE;
RV_TRANSPORT_OUT TRUE;
RV_SASS3_SUPPORT TRUE;

2. If you use the RTRTIBFidDb to download the data dictionary from the network, you must
configure the RTIC to send the data dictionary to clients in the rtic.cf.
PROVIDE_DATA_DICTIONARY TRUE;
APPENDIX_A /var/triarch/appendix_a
ENUMTYPE_DEF /var/triarch/enumtype.def

3. If you are publishing to a new service, you must configure rtic.cf to accept the messages for
that service.
BROADCAST
{
SOURCE “MYSOURCE”;
# ...
}

4. If any of the the following configuration values are specified in the rtic.cf:
RV3_OUTPUT_SERVICE
RV3_OUTPUT_NETWORK
RV3_OUTPUT_DAEMON
RV3_PUBLISH_SERVICE
RV3_PUBLISH_NETWORK
RV3_PUBLISH_DAEMON
then SFC publishers will need to include the following configuration in the SFC configuration
file:
*enablePingSubscription : false

SFC Developer’s Guide 388


APPENDIX E: RMDS INFRASTRUCTURE

Also, to download a dictionary for the publisher, a RTRTIBFidDb will need to be created
external to the publishing service, using a different RTRTIBConnection. See section 5.5.4.3 for
an example of the workaround.
5. If the following configuration is in the RTIC’s Market Data Hub configuration file (typically
triarch.cnf):
*sectorName : REC ! anything besides the default value “ANY”
and SFC includes the configuration
*serviceProvider : RTIC
then SFC must configure the default sector.
*defaultSector : REC
See section 5.5.6.2 for details.
6. The following configuration variables must be set in TMF’s configuration file:
SUPPORT_SASS3 TRUE
APPENDIX_A /var/triarch/appendix_a
ENUMTYPE_DEF /var/triarch/enumtype.def
RV_UPDATE_SERVICE # match value from RTIC’s RV3_OUTPUT_SERVICE
RV_UPDATE_NETWORK # match value from RTIC’s RV3_OUTPUT_NETWORK
RV_INITIAL_SERVICE # match value from RTIC’s RV3_SERVICE
RV_INITIAL_NETWORK # match value from RTIC’s RV3_NETWORK
Services must be included in SUBJECTS. For example
SUBJECTS
{
ISFS...;
IDN_RDF...;
}
7. SFC’s updateService and updateNetwork configuration variables must match these values
in the TMF’s configuration file:
RV_OUT_SERVICE
RV_OUT_NETWORK
8. For the RTIC to detect when broadcast, local publishers die, the following configuration must
be set:

SFC Developer’s Guide 389


APPENDIX E: RMDS INFRASTRUCTURE

BC_DQA_MODE TRUE;
FEED_FAIL_TIMEOUT 120; # if a message not received every 120
# seconds stale messages are sent for all items.
This mechanism requires RTIC 10.1 or later. The groupId must also be configured in the SFC
publisher. See section 5.5.5.1 for details.
9. If any of the following configuration is set, then the RTIC may have been configured to support
legacy TIB applications.
FIELDS “tss_fields.cf”;
RECORDS “tss_records.cf”;
CI_SASS2_SUPPORT TRUE;
CI_TRANSPORT_OUT TRUE;
CI_TRANSPORT_IN TRUE;
RV_SASS2_SUPPORT TRUE;
RV2_*
When this configuration is set, the RTIC has been configured to look like a TIC. SFC
applications should be configured as if deployed on a TIB/SASS3 network. SFC does not
support the SASS2 or CI protocols to or from an RTIC.
Note that this configuration should only be used for specific migration situations.
Other configuration may be needed depending on your environment and usage.

SFC Developer’s Guide 390


APPENDIX G: DACS LIBRARY FUNCTIONS
G.1 DACS_CsLock()

Synopsis
DACS_CsLock (nm_channel, item_name, newLock, newLockLen, lockList, Dacs_Error)
int nm_channel
char *item_name
unsigned char **newLock
int *newLockLen;
COMB_LOCK_TYPE lockList[];
DACS_ERROR_TYPE *Dacs_Error

Description
This function is called to combine a list of access locks into a single composite DACS access lock. This
function is used to form complex access locks from constituent access locks that were created by a
previous call to the DACS_CsLock() or DACS_GetLock() functions.

Function Arguments
nm_channel
The nm_channel parameter is no longer used but it must be 0 (zero) for backward
compatibility.
item_name
The item_name parameter must be an empty string (“”). (This is also for backward
compatibility.)
newLock
The newLock parameter is a pointer to an unsigned char pointer that shall point to the
generated access lock for the “item” built by the source/compound server. If the pointer is
NULL on entry to the DACS_CsLock() function, space for the new access lock will be
dynamically allocated using malloc(). It is the responsibility for the caller of DACS_CsLock()
to free() the memory allocated when the newly generated access lock is no longer required.

SFC Developer’s Guide 391


APPENDIX G: DACS LIBRARY FUNCTIONS

newLockLen
The newLockLen parameter is updated to reflect the length of the newly generated lock. If
the newLock parameter does not point to a NULL pointer, then the source/compound server
application must supply the *newLockLen with the maximum size of the user-supplied
access lock pointer. If the *newLockLen parameter supplied by the source/compound server
application is less then the length required to fit the access lock, a PERM_FAILURE error is
returned.
lockList
The lockList parameter is a pointer to an array of pointers to the access locks of associated
component items to be combined by the source/compound server. A NULL pointer terminates
the list.
Dacs_Error
The Dacs_Error parameter points to a data structure of type DACS_ERROR_TYPE in which
returned errors will be placed.

Data Structures
The COMB_LOCK_TYPE data structure is defined to be as follows:
typedef struct {
int server_type;
char *item_name;
unsigned char *access_lock;
int lockLen;
} COMB_LOCK_TYPE;
where:

server_type must be set to 0 (zero).


item_name is a NULL pointer (for backward compatibility).
access_lock is a pointer to the user-supplied access lock that is to be used as one
of the constituent item access locks.
lockLen is the length of the access lock. This value was previously returned
from a DACS_GetLock() function.

SFC Developer’s Guide 392


APPENDIX G: DACS LIBRARY FUNCTIONS

The DACS_ERROR_TYPE data structure is defined to be as follows:


typedef struct {
short dacs_error;
short dacs_suberr;
} DACS_ERROR_TYPE;

Return Values
This function returns DACS_SUCCESS if the function did not encounter a fatal error, and the
newLock and newLockLen parameters shall be populated.
DACS_FAILURE is returned if a fatal unrecoverable error was encountered. An ASCII explanation of
the error can be further determined by passing the Dacs_Error data structure to the DACS_perror()
function.

SFC Developer’s Guide 393


APPENDIX G: DACS LIBRARY FUNCTIONS

G.2 DACS_GetLock()

Synopsis
DACS_GetLock (service_type, ProductCodeList, LockPtr, LockLen, Dacs_Error)
int service_type;
PC_LIST *ProductCodeList;
unsigned char **LockPtr;
int *LockLen;
DACS_ERROR_TYPE *Dacs_Error;

Description
This function is used to make a DACS access lock from a list of entitlement codes (i.e., codes specified
by the data vendor on which all permissioning is based).

Function Arguments
service_type
The service_type parameter is used to pass the service type of the server that is to be
encoded into the DACS access lock. This value is a unique numeric ID assigned to a Triarch
service by the service’s serviceId parameter in the global Triarch configuration file.
ProductCodeList
The ProductCodeList parameter is used to pass the list of entitlement codes which shall be
encoded into the DACS access lock.
LockPtr
The LockPtr parameter is a pointer to an unsigned char pointer that shall point to the
generated access lock that represents the entitlement code list in DACS lock format. If the
pointer is NULL on entry to the DACS_GetLock() function, space for the new access lock will
be dynamically allocated using malloc(). It is the responsibility for the caller of
DACS_GetLock() to free() the memory allocated when the newly generated access lock is
no longer required.

NOTE: If the DACS_GetLock() function returns an error, then no space for the access
lock will have been allocated.

SFC Developer’s Guide 394


APPENDIX G: DACS LIBRARY FUNCTIONS

LockLen
The LockLen parameter is a pointer to an int. This parameter is updated to reflect the length
of the newly generated access lock. If the LockPtr parameter does not point to a NULL
pointer on entry, then the user must supply the LockLen with the maximum size of the user-
supplied access lock buffer. If the user-supplied LockLen is less then the length required to
fit the access lock, then a DACS_FAILURE error is returned.
Dacs_Error
The Dacs_Error parameter points to a data structure of type DACS_ERROR_TYPE in which
returned errors will be placed.

Data Structures
The PC_LIST data structure is defined to be as follows:
typedef struct {
char operator;
unsigned short pc_listLen;
unsigned long pc_list[/* pc_listLen */];;
} PC_LIST;
where:

operator is the user-supplied operation that shall be imposed on the entitle-


ment code list that is supplied. The operator field must have one of
the following formats.

The ampersand character ‘&’ (for an “AND” list) — The implication is


that the user of the item must be permissioned for all the entitlement
codes contained within the access lock.

The vertical bar character ‘|’ (for an “OR” list) — The implication is that
the user of the item only needs access to any one of the entitlement
codes contained within the access lock.
pc_listLen is used to flag the number of entries that are contained within the
pc_list array.

SFC Developer’s Guide 395


APPENDIX G: DACS LIBRARY FUNCTIONS

pc_list is a numerically ascending sorted list of unsigned long values that


shall be interpreted as the entitlement codes to be encoded into a
DACS access lock.

The DACS_ERROR_TYPE data structure is defined to be as follows:


typedef struct {
short dacs_error;
short dacs_suberr;
} DACS_ERROR_TYPE;

Return Value
This function returns DACS_SUCCESS if the function did not encounter a fatal error.
DACS_FAILURE is returned if a fatal unrecoverable error was encountered. An ASCII explanation of
the error can be further determined by passing the Dacs_Error data structure to the DACS_perror()
function.

SFC Developer’s Guide 396


APPENDIX G: DACS LIBRARY FUNCTIONS

G.3 DACS_CmpLock()

Synopsis
DACS_CmpLock (Lock1Ptr, Lock1Len, Lock2Ptr, Lock2Len, Dacs_Error)
unsigned char *Lock1Ptr;
int Lock1Len;
unsigned char *Lock2Ptr;
int Lock2Len;
DACS_ERROR_TYPE *Dacs_Error;

Description
This function is used to compare two access locks for equality. This function can be used to verify
whether or not a new access lock is different from a previously generated access lock, thus reducing
the possible overhead incurred in redistribution of an unchanged access lock.

Function Arguments
Lock1Ptr
The Lock1Ptr parameter is a pointer to the first access lock that is to be compared.
Lock1Len
The Lock1Len parameter is an integer. This parameter is the length of the first access lock
that is to be compared.
Lock2Ptr
The Lock2Ptr parameter is a pointer to the second access lock that is to be compared.
Lock2Len
The Lock2Len parameter is an integer. This parameter is the length of the second access
lock that is to be compared.

Return Value
This function returns DACS_SUCCESS if the function did not encounter a fatal error and the access
locks were logically identical.

SFC Developer’s Guide 397


APPENDIX G: DACS LIBRARY FUNCTIONS

DACS_DIFF is returned if a fatal error was not encountered but the two access locks were logically
different.
DACS_FAILURE is returned if a fatal unrecoverable error was encountered. An ASCII explanation of
the error can be further determined by passing the Dacs_Error data structure to the DACS_perror()
function.

SFC Developer’s Guide 398


APPENDIX G: DACS LIBRARY FUNCTIONS

G.4 DACS_perror()

Synopsis
DACS_perror (err_buffer, buffer_len, text, Dacs_Error);
unsigned char *err_buffer;
int buffer_len;
unsigned char *text;
DACS_ERROR_TYPE *Dacs_Error;

Description
This function is used to create a textual message describing the last error generated by a DACS
Library call. The message is saved to the supplied buffer. The error number is taken from the location
Dacs_Error -> dacs_errno variable pointed to by the user application, when a library function returns
a DACS_FAILURE.

Function Arguments
err_buffer
The err_buffer parameter contains the destination address for the generated error string. If
the supplied buffer is smaller then the generated error string, DACS_FAILURE will be
returned.
buffer_len
The buffer_len is a variable that indicates the maximum size of the err_buffer.
text
The text parameter is a pointer to a null-terminated character string that is placed into the
buffer before the DACS error message. This string and the error message will be separated
by a colon and a blank space. If an empty character string is specified, only the DACS Library
error message will be placed into the err_buffer.
Dacs_Error
The Dacs_Error parameter points to a data structure of type DACS_ERROR_TYPE into
which returned errors shall be placed.

SFC Developer’s Guide 399


APPENDIX G: DACS LIBRARY FUNCTIONS

Return Values
This function returns DACS_SUCCESS if the function did not encounter a fatal error.
DACS_FAILURE is returned if a fatal unrecoverable error was encountered.

SFC Developer’s Guide 400


INDEX

Symbols C
_RV.ERROR.RV.DATALOSS 309 cache 286, 357, 358
_RV.ERROR.RV.DATALOSS.INBOUND 309 cache duplication 357
_RV.ERROR.RV.DATALOSS.OUTBOUND 309 cacheType 286
_RV.ERROR.SYSTEM.CLIENT.FASTPRODUCER channel 348
308 class identifier 245, 250
_RV.ERROR.SYSTEM.CLIENT.NOMEMORY 308 class names 3
_RV.ERROR.SYSTEM.CLIENT.SLOWCONSUMER COMB_LOCK_TYPE structure 2
308 communication protocols 203, 217
_RV.ERROR.SYSTEM.LICENSE.EXPIRE 308 configuration file 361
_RV.WARN.SYSTEM.EVENTLOOP.STARVATION configuration variables 330
308 configuring software components 244
connected() method 204
A connection parameters 325
connection timeout 364
abstraction 6, 7
contributions 324
access locks 371, 2
control loop 13, 46, 260
accessing pages from a service 162
creating record fields 69
accessing records from a service 43
Custom Event Loop 237
accessing time-series from a service 180
addClient() method 19, 196
allowUpdatesToChangeStateToOk 308 D
ANSI data 141, 293, 322 DACS 270, 355
appendix_a 283, 292, 304, 306 DACS Access Locks 272
application ID 271 DACS Daemon 274
application name 362 DACS_CmpLock() 7
assertions 8, 9, 278 DACS_CsLock() 1
automatic data recovery 355 Dacs_Error 2, 5, 9
DACS_ERROR_TYPE structure 3, 6
B DACS_GetLock() 4
DACS_perror() 9
Backus Naur Form (BNF) notation 270
DACS_retry_connection_interval 274
boolean type 4
DACS_user_login_retry_interval 275
buffer read iterator 159, 163
Data dictionary
buffer write iterator 196
customizing for performance 283
buffer_len (DACS Library) 9
data dictionary 301, 302, 303, 304, 306, 380, 388
buffers 367, 369
data item 11
data samples 172

SFC Developer’s Guide 401


Index

data status user based entitlements 266


item 307 enumerations 293
service 307 err_buffer (DACS Library) 9
data stream 156, 329 error logging 364
database ETIC 340
configuration variables 55, 245, 250, 261 event dispatching loop 235
field definitions 39, 81, 176 event logging 253
dataLossInboundInterval 309 event notifier 235
dataLossOutboundInterval 309 events
Debug arrival and departure of services 18
configuration 289 field updates 16
decimalSize 297 I/O 236
decimalSize 292, 297 logging 253
defaultSector 317 page state changes 141
delimiter character 369 page updates 149, 167
design by contract 8 propagation to clients 19, 218
dispatchInterval 327 received from RTRRTPage 149, 160
DQA 382, 390 received from RTRRTRecord 41
dropClient() method 19, 32, 196 record state changes 16, 71
DTIC 311, 379, 385 record udpates 47
service state changes 17, 145, 158
E timing 211
example applications 87
effects pages 141, 322, 323
enableEntitlements() method 269
encapsulation 7 F
Entitlements failover 359
configuration 276, 326, 327 fault tolerance 354
configuration for DACS access locks 272 FID database 301
content based entitlements 266 fidDbLocation 302
Publishing Entitlement Data 267 field definition 15, 39, 81, 176
required config for DACS access locks 272 field identifier 15
required config for publishing DACS locks 272 field updates 34
service name mapping requirement 272, 273 Field-to-Field implementation 87
subject based entitlements 266 Field-to-SSL implementation 87
supported configurations 267 forceInfrastructureDrivenRecovery 310
Trouble forceSFCDrivenRecovery 310
entitlement data is not published 272 function names 4
lock data does not get published 273

SFC Developer’s Guide 402


Index

G load level 357


localSubjectMapFile 316
globalSujectMapFile 316
lock 2
Lock1Len (DACS Library) 7
H Lock2Len (DACS Library) 7
hash table size 279 LockLen (DACS Library) 5
Hint 296 lockList (DACS Library) 2
historical record of market activity 172 LockP1tr (DACS Library) 7
LockP2t (DACS Library) 7
I LockPtr (DACS Library) 4
log file 289, 290
image pacing 287
Logging 278
imageInterval 288
imagesPerInterval 288
Inactive event 21, 23, 29, 76 M
indicateInsertFailed() method 194 Mapping SFC symbol names to TIB subject names 85
indicateInsertSucceeded() method 194 Market Data Hub 264
Infrastructure compatibility 291 Marketfeed 300, 301
initialOpenLimit 288 maxCache 286
In-process RTRRTRecordService Publisher 86 memory management guideline 4
insert client 193 memory usage 278, 282, 283
insert data 193 message buffers 369
insert server 194 message read iterator 204
insert service 193 message session 203
instance ID 362 pseudo-code for reading/writing messages 206
instance identifier 246, 250 TCP implementation 218
IPC mechanism 351 message session client 205, 211
IPC message tracing 368 message write iterator 204
ipcRoute 364 MFC 236
ipcRouteName 365 model
IPCServerName 366 message session 203
item_name (DACS Library) 1 real-time pages 141, 144, 158
real-time record publication 80
K real-time records 15, 36
SFC infrastructure 226
Keep Alive messages 360
software configuration 244
TCP client/server 218
L time-series 172, 175
lastMessageReceived() method 204 modularity 7

SFC Developer’s Guide 403


Index

mount option 365 pending limit 284


MS Windows 13, 249 performance 278
permissioning 355
N permissioning information 270
ping messages 370
N2_UBMS 320
pingInterval 370
Network Management Agent 355
pool events 54
newInsert() method 193
preemption 354, 357
newLock (DACS Library) 1
preemptionLocation 286
newLockLen (DACS Library) 2
pre-load SFC’s cache 282, 288
news headlines 320
price field 292
newsEnabled 320
processInsertRequest() method 194
newsPrefix 321
processNewSession() method 219
newsSectorList 321
processRTRecordServiceAdd() method 54
nm_channel (DACS Library) 1
processSeriesComplete() method 191
notFoundAsRecoverable 307
processSessionMessage() method 206
NotStale event 20
processSnapshotSync() method 43
number_of_items 279, 286, 316
processStreamSync() method 163
processTimerEvent() method 236
O processUpdateComplete() method 50
open system design 353 ProductCodeList (DACS Library) 4
openLimit 286 providers of record items 17
outstanding image requests 371 Published records 61
Publisher
source driven 287
P Publisher service 62
page pubSubjectPrefix 85
attributes 323 putInstanceVariable() method 251
configuration 323
next page 320
previous page 320 Q
page client 156, 160 QForm 379
page data 141, 145, 158, 163
page records 322 R
page service 145, 156, 158
real-time record 16
page service pool 157
real-time record model 35
page snapshot 148, 160
REC_TYPE 300, 301
page state 141, 143, 157
record chain 17
PC_LIST structure 5

SFC Developer’s Guide 404


Index

record client 15, 41 Tick event 68


record data 15, 37, 80 Triarch/SSL application main() 112
record iterator 33, 37, 38, 81 UpdateComplete event 68
Record publication Updating record fields 71
accessing records 73 valid field types 69
adding fields 69 Record publishing 61
Changing record state 72 sending message 282
CloseTick event 68 setting field 280
CorrectionTick event 68 record service 17, 39, 81
creating new fields 69 record service pool 18
DACS access lock entitlement format 78 record service state 17
GroupNotStale event 76 record state 15, 19, 71
GroupStale event 76 record template 288, 356
Inactive event 67 record templates 292, 300, 301
Informational events 67 recovery queue 360
In-process publisher service 86 recovery, led by Service Distributor 358
managing record resources 79 registering interest in
mapping fiddef types to field types 70 field events 16
mixed mode 65 I/O events 236
NotStale event 67 insert notifications 196
publishing entitlement data 77 page events 141
publishing to Triarch 83 pool events 54
Record Initialization 69 record events 15
record state 65 Rendezvous 5 328
Record state diagram 65 Rendezvous 6 328
removing records 65 Rendezvous advisory messages 308
Resync event 66 Rendezvous connection parameters 325
ResyncComplete event 67 Rendezvous Distribution Layer 264
resynchronizing record data 73 request queue 284
RTRRTRecordImpl 62 request routing 355, 358
RTRRTRecordServiceImpl 62 request throttling 354
sink-driven mode 64 request timing 285
source-driven mode 63 requestTS1RealTime 173
Stale event 67 resiliency 354, 359
states and events 69 resource allocation 17
Sync event 66 resource management 354, 358
TIB publisher service 85 resource optimization 354, 355
TIB subject names 85 resource usage 353

SFC Developer’s Guide 405


Index

response timing 354 RTRMgmtEvent 253, 262


Resync event 20 RTRObjectId 245, 247, 261
retry queue 355 RTRPage 142
Reuters Reliable Datagram Protocol (RRDP) 352 RTRPageClient 142
RIC 312, 314 RTRPageRegion 142
RMDS infrastructure 264 RTRPageRegionClient 142
RTR prefix 4 RTRPageService 156
RTRBOOL 4 RTRPageServicePool 157
RTRBufferReadIterator 159, 163 RTRPageServicePoolClient 157
RTRConfig 252, 261 RTRRecordChain 17, 19, 39
RTRConfigDb 245, 250, 261 RTRRecordChainClient 17, 19, 39
RTRConfigVariable 245, 261 RTRRecordChainElement 17, 19, 39
RTRDefaultConfigDb 252, 262 RTRRecordChainElementClient 17, 19, 39
RTRDefaultInsertServicePool 194, 196 RTRRecordChainIteratorPtr 39
RTRDefaultLogger 254, 255, 262 RTRRegistryDb 250, 262
RTRDefaultRTPageService 36, 146, 159, 165 RTRRequestItem 284
RTRDefaultRTPageServicePool 159 RTRRTAlphanumericField 16, 61
RTRDefaultRTRecordService 46 RTRRTField 16, 33, 37, 81, 280
RTREventNotifier 13, 235, 260 RTRRTFieldClient 35, 38, 283
RTREventNotifierInit 235 RTRRTFieldClients 280
RTRExternalValue 261 RTRRTFieldToFieldRecordService 282
RTRFidDb 39, 81 RTRRTFieldToSSLRecordService 265
RTRFidDefinition 15, 39, 82 RTRRTFieldToTIBRecordService 265
RTRField 280 RTRRTFieldUpdateList 72, 281
RTRFileFidDb 265, 303, 306 RTRRTPage 145, 156, 158
RTRInsert 193 RTRRTPageClient 145, 149, 156, 158, 160
RTRInsertClient 193 RTRRTPageService 145, 156, 158
RTRInsertService 193, 194 RTRRTPageServicePool 145, 157, 158
RTRInsertServiceClient 194 RTRRTPageServicePoolClient 145, 157, 158
RTRIOClient 236, 260 RTRRTRecord 16, 30, 33, 37, 80
RTRListOfExternalValue 261 RTRRTRecordClient 16, 31, 32, 37, 41, 81
RTRMDConnection 269 RTRRTRecordImpl 62
RTRMDServiceClient 39, 81, 145, 146, 158, 159 RTRRTRecordImplClient 80
RTRMDSServicePoolFactory 331 RTRRTRecordIterator 37, 50, 81, 280
RTRMessageReadIterator 204 RTRRTRecordService 18, 38, 81
RTRMessageSession 204, 217 RTRRTRecordServiceImpl 62
RTRMessageSessionClient 204, 205, 211 RTRRTRecordServiceIterator 279
RTRMessageWriteIterator 204 RTRRTRecordServicePool 18, 38

SFC Developer’s Guide 406


Index

RTRRTRecordServicePoolClient 18, 38, 54 RTRTSValDefDbClient 176


RTRRTRecordUpdateIterator 34, 37, 50, 81, 280 RTRUTF8String 263
RTRSelectNotifier 13, 46, 235, 261 RTRWindowsNotifier 235, 236, 261
RTRSeriesValue 176 RTRXFileDb 247, 262, 286
RTRSeriesValueDefinition 176 RTRXtNotifier 241, 261
RTRServiceCustomizer 316 RTRXViewNotifier 243, 261
RTRSimpleSeries 173, 176
RTRSnapshotField 16, 38 S
RTRSnapshotRecord 16, 38
samples provided by time-series 172
RTRSnapshotRecordClient 16, 38
SASS3 307, 378
RTRSnapshotRecordIterator 38
sector 311, 312, 314, 322
RTRSnapshotRecordService 39
sectorList 316
RTRSSLConnection 265, 268, 270
select() system call 13, 261
RTRSSLConnectionServer 265, 268, 270, 273
sendInsert() method 196
RTRSSLDispatcher 165, 265
sendSymbolFields 293
RTRSSLInsertRequest 194
service 12, 354, 356
RTRSSLInsertService 265
added to or removed from network 359
RTRSSLPageService 265
Service Distributor 357, 358
RTRSSLRTRecordService 265
restart after failure or interruption 358
RTRSSLServicePoolFactory 265, 310
service ID 272, 276, 371
RTRString 261
service pool 18, 53
RTRTcpClientSession 218, 223
service pool factory 302, 310
RTRTcpServerSession 218
service state 17
RTRTcpSessionServer 218
service_type (DACS Library) 4
RTRTIBConnection 265, 268, 270, 273, 327
serviceId 370
RTRTIBCustomizer 265, 314, 316, 318, 321
serviceProvider 311
RTRTIBFidDb 265, 303, 304, 306
setRecordTemplateNumber() method 301
RTRTIBPageService 265
setView() method 187
RTRTIBRTRecordService 265
Simple Network Management Protocol (SNMP) 355
RTRTIBServicePoolFactory 265, 310, 327
single open 355
RTRTimerCmd 211, 236, 261
sink application 350
RTRTimeSample 172, 175
Sink Distributor 351
RTRTimeSeries 172, 175, 187
sink-driven source server 357
RTRTimeSeriesClient 172, 176, 178
snapshot record 16
RTRTimeSeriesService 173, 176
snapshot record data 38
RTRTS1TimeSeriesService 176, 182
snkResponseThrottle 371
RTRTSAInsertService 265
Source Distributor 272, 286, 287, 324
RTRTSValDefDb 176
source led recovery 358

SFC Developer’s Guide 407


Index

source server 356 Sync event 20, 22, 28, 50, 75


failure and recovery 359
source-driven 63 T
source-driven source server 357
TCP client 218
SSL Adapter 311, 312
TCP/IP 218, 352, 353, 355
SSL configuration 327, 330
tcpNoDelay 327
SSL implementation 264
tcpQuickAck 371
SSL session 36, 159, 165
text (DACS Library) 9
SSL_ET_SESSION_ACCEPTED event 367, 369,
text() method 21, 29, 31, 67, 76
370, 371
threads 328
SSL_OPT_IPC_SERVER_NAME option code 366
threshold limit 357
SSL_OPT_LOG_EVENT_FAIL option code 363
throttle 354, 371
SSL_OPT_MAX_UNCONFIRMED_MSG_COUNT
TIB 4-part subject 312, 318
option code 367
TIB effects pages 322
SSL_OPT_SESSION_TIMEOUT option code 370
TIB implementation 264
SSL_SNK_MAX_RETRY_DELAY option code 367
TIB Publisher Service 85
SSL_SNK_MIN_RETRY_DELAY option code 368
timer command 211, 261
SSL_SNK_MO_IPC_ROUTE_NAME option code 365,
timer events 236
366
time-series client 172, 178
SSL_SNK_RESPONSE_THROTTLE option code 371
time-series data 172
SSL_SRC_MAX_SESSIONS option code 366
time-series service 173
SSLAPI_CONFIG 361
TMF 227, 325, 379, 386
sslErrorLog() 364
Tracing 278
sslMsgMount() 369
trapping log events 254
sslMsgOpen() 369
Triarch 264
sslQueryInterface() 363, 364
Triarch Publisher Service 83
sslSetProperty() 363
TS1 data 176
sslSnkMount() 364, 369, 370, 371
tss_fields.cf 303, 304, 306, 379
sslSrcMount() 371
sslSrcMount() 366
Stale event 20, 29, 75 U
state transitions 20, 28, 65, 75 unconfirmed messages 367
states 11 update event 32, 37, 68, 81
stopPublicationWhenDACSDowns 274 updateDaemon 325
stopSubscriptionWhenDACSDowns 274 updateNetwork 325
stream client 156 updates to record fields 71
subject map file 316, 317 updateService 325
subjectMapSize 316 Updating fields 72

SFC Developer’s Guide 408


Index

username 270
username method 270

V
variable() method 247, 250
version number 362

W
Windows 235
Windows NT registry 249

X
X-Windows 13, 247

SFC Developer’s Guide 409

You might also like