Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE ›...

264
Application Development with TME 10 ADE Version 3.6 September 1998

Transcript of Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE ›...

Page 1: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Development withTME 10 ADE

Version 3.6September 1998

Page 2: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME
Page 3: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Development with TME 10 ADE (September 1998)Copyright NoticeCopyright © 1998 by Tivoli Systems, an IBM Company, including this documentation and all software.All rights reserved. May only be used pursuant to a Tivoli Systems Software License Agreement orAddendum for Tivoli Products to IBM Customer or License Agreement. No part of this publication maybe reproduced, transmitted, transcribed, stored in a retrieval system, or translated into any computerlanguage, in any form or by any means, electronic, mechanical, magnetic, optical, chemical, manual, orotherwise, without prior written permission of Tivoli Systems. The document is not intended forproduction and is furnished “as is” without warranty of any kind.All warranties on this document arehereby disclaimed including the warranties of merchantability and fitness for a particular purpose.

Note to U.S. Government Users—Documentation related to restricted rights—Use, duplication ordisclosure is subject to restrictions set forth in GSA ADP Schedule Contract with IBM Corporation.

TrademarksThe following product names are trademarks of Tivoli Systems or IBM Corporation: AIX, IBM, OS/2,RS/6000, Tivoli Management Environment, and TME 10.

Microsoft, Windows, Windows NT, and the Windows logo are trademarks or registered trademarks ofMicrosoft Corporation.

UNIX is a registered trademark in the United States and other countries licensed exclusively throughX/Open Company Limited.

Other company, product, and service names mentioned in this document may be trademarks orservicemarks of others.

NoticeReferences in this publication to Tivoli Systems or IBM products, programs, or services do not imply thatthey will be available in all countries in which Tivoli Systems or IBM operates. Any reference to theseproducts, programs, or services is not intended to imply that only Tivoli Systems or IBM products,programs, or services can be used. Subject to Tivoli Systems’ or IBM’s valid intellectual property or otherlegally protectable right, any functionally equivalent product, program, or service can be used instead ofthe referenced product, program, or service. The evaluation and verification of operation in conjunctionwith other products, except those expressly designated by Tivoli Systems or IBM, are the responsibilityof the user.

Tivoli Systems or IBM may have patents or pending patent applications covering subject matter in thisdocument. The furnishing of this document does not give you any license to these patents. You can sendlicense inquiries, in writing, to the IBM Director of Licensing, IBM Corporation, 500 Columbus Avenue,Thornwood, New York 10594.

Page 4: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME
Page 5: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Development with TME 10 ADE i

Application Developmentwith TME 10 ADE

Preface.................................................................................................................... v

Chapter 1—Anatomy of a TME 10 ADE ApplicationIntroduction to Tivoli/Phone...............................................................................1-1

Installation...........................................................................................................1-2

Introduction to Object-oriented Applications .....................................................1-2

TME 10 ADE Development Cycle .....................................................................1-3

Application Analysis and Design........................................................................1-4

Problem Analysis .......................................................................................1-5

The Profile Object Model...........................................................................1-7

Identifying Classes and Operations............................................................1-8

The Profile Class................................................................................1-8

The Endpoint Class..........................................................................1-12

Design Issues in TME 10 ADE Applications ...................................................1-14

Transactions..............................................................................................1-14

Security.....................................................................................................1-14

Exceptions ................................................................................................1-17

Scalability.................................................................................................1-18

Customizations and Extensibility.............................................................1-20

Internationalization...................................................................................1-21

Summary ...........................................................................................................1-22

Chapter 2—Defining an Application with IDLInterface Definition.............................................................................................2-2

IDL Data Types..........................................................................................2-2

Exception Declarations...............................................................................2-4

Specifying Interfaces..................................................................................2-6

PhoneListProfile Interface Definition................................................2-7

plbo Interface ...................................................................................2-11

Page 6: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

ii Version 3.6

Implementation Specification........................................................................... 2-12

Class Declaration ..................................................................................... 2-12

Tivoli/Phone Implementation Specification ............................................ 2-14

PhoneListProfile Class .................................................................... 2-14

PhoneEndpoint Class....................................................................... 2-17

Program Specification....................................................................................... 2-18

Per-method Servers .................................................................................. 2-21

Daemon Servers ....................................................................................... 2-22

Tivoli/Phone Program Specification ........................................................ 2-24

PhoneListProfile Class .................................................................... 2-24

PhoneEndpoint Class....................................................................... 2-27

Installation Specification .................................................................................. 2-28

PhoneListProfile Installation Specification.............................................. 2-28

PhoneEndpoint Class Installation Specification ..................................... 2-34

Compiling an IDL Specification....................................................................... 2-39

Chapter 3—Method ImplementationsThe initializ Method............................................................................................ 3-2

Representing Application Data......................................................................... 3-13

Record Creation ................................................................................................ 3-16

Record Retrieval ............................................................................................... 3-22

Record Deletion ................................................................................................ 3-27

Record Modification Method............................................................................ 3-30

Chapter 4—Implementations for CCMS MethodsPolicy-related Methods....................................................................................... 4-2

Changing Profile Policy ............................................................................. 4-2

Enabling and Disabling Validation ............................................................ 4-9

The validate Operation............................................................................. 4-12

Removing a Profile ........................................................................................... 4-14

Populating a Profile from a File........................................................................ 4-16

Moving and Copying Records .......................................................................... 4-21

Page 7: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Development with TME 10 ADE iii

Chapter 5—Creating Scalable OperationsScalable Input Data with IOM ............................................................................5-2

Scalable Output Data with Iterators ..................................................................5-13

Implementing an Iterator-based Method ..................................................5-15

Implementation: Initial Method................................................................5-18

Implementation: Iterator Service Method ................................................5-20

The Iterator Engine...................................................................................5-21

Chapter 6—Profile Endpoint MethodsProfile Endpoint Behavior ..................................................................................6-2

Importing Profile Records...................................................................................6-4

Post-distribution Processing..............................................................................6-14

Chapter 7—Creating an Application User InterfaceThe Tivoli/Phone Graphical Interface ................................................................7-2

Components of a Graphical Interface .................................................................7-6

Dialogs........................................................................................................7-7

Dialog States...............................................................................................7-8

Presentation Objects ...................................................................................7-9

Callbacks ..................................................................................................7-11

The Gadget Library...........................................................................................7-12

The Gadget Hierarchy ..............................................................................7-13

The Dialog Gadget Object........................................................................7-14

Gadget Library Callbacks.........................................................................7-14

Launching a Dialog...........................................................................................7-18

Managing Tabular Data ....................................................................................7-24

The Display Cache ...................................................................................7-26

Creating a Display Cache ................................................................7-27

Freeing a Display Cache..................................................................7-31

Other Cache-related Operations ......................................................7-31

Registering a Table...................................................................................7-32

Page 8: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

iv Version 3.6

Defining Table Columns.......................................................................... 7-34

The Expose Mechanism ........................................................................... 7-38

Manipulating Table Rows........................................................................ 7-40

Using the TME 10 Support Dialogs ................................................................. 7-43

Chapter 8—Writing Client ProgramsClient Program Requirements............................................................................. 8-2

Tivoli/Phone CLI Commands............................................................................. 8-3

Appendix A—Tivoli/Phone Build EnvironmentThe Tivoli/Phone Source Tree........................................................................... A-2

Building Tivoli/Phone ....................................................................................... A-4

The Export Directory ......................................................................................... A-4

Creating a Multi-platform Environment ............................................................ A-6

General Defaults........................................................................................ A-6

Platform-specific Definitions .................................................................... A-7

Implicit Build Rules ................................................................................ A-10

Endpoint-specific Rules and Macros ...................................................... A-12

Page 9: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Preface

Application Development with TME 10 ADE v

PrefaceTME 10 (Tivoli Management Environment 10) is a softwareenvironment, composed of a suite of integrated software products,designed specifically for distributed system management. TME 10brings coherence and the quality control found in mainframe systemsto the challenge of managing multiple operating systems, networkservices, diverse system tasks, and constantly changing nodes andusers. TME 10 encourages a team approach to distributed systemmanagement; senior system administrators can focus on analysis,strategy, and security issues, leaving the routine and daily tasks to staffadministrators.

The TME 10 Advanced Developer’s Environment (TME 10 ADE),provides the added advantage of access to an equally powerfuldevelopment environment. TME 10 ADE is compatible with thefeatures specified by the Common Object Request Broker Architecture(CORBA) provided by the Object Management Group (OMG). TheCORBA Specification defines a client/server system, in which theclient and server are completely separated.

TME 10 ADE encompasses a large array of services, and it is oftendifficult for a developer new to it to make sense of how these servicesfit together to form an application.

To provide a road map to application development, this book stepsthrough the design and implementation of a sample TME 10 ADEapplication. The application is called Tivoli/Phone. Each chapterbuilds on the previous, taking the application from the design phase,to Interface Definition Language (IDL) specification, and on tomethod server implementation. The final chapters of the book discusshow to create user interfaces for an application (both graphical andnon-graphical).

The source code to the Tivoli/Phone application is also availableon-line. You are welcome to modify and re-use this code. You canmodify the application to experiment with different services, or youcan use the code as a starting point for your own application.

Page 10: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Preface

vi Version 3.6

Who Should Read This GuideThis manual explains concepts you should know to effectively useTME 10 ADE to develop applications in a heterogeneous environment.Readers of this manual should have a knowledge of the UNIXoperating system and the C programming language.

Programmers writing applications that will be installed on the TivoliManagement Platform or modifying Tivoli applications should readthis book.

Prerequisite and Related DocumentsAlthough this book is intended as an introductory text, many of thediscussions assume a simple knowledge of TME 10 ADE concepts andservices. If you are new to Tivoli and TME 10 ADE, you should readthe following selections before tackling this book:

■ ReadApplication Development for the Lightweight ClientFramework to understand the concepts of the LCF and LCFendpoints. This manual assumes that you understand the LCF, thetype of endpoints it supports, and how these endpoints differ fromthe managed node endpoint.

■ Read Chapters 1 and 2 of theIntroduction to TME 10 ADE. Thesechapters are an excellent overview of the application servicesTME 10 ADE provides.

■ Read the introductory portion of Chapter 4 of theApplicationServices Manual, Vol. II. This chapter covers the Configurationand Change Management Service (CCMS). You shouldfamiliarize yourself with CCMS concepts, since the Tivoli/Phoneapplication discussed in this book is based on it.

While reading this book, you may find that you want more detailedinformation about a particular concept or service. The following listshould give you an idea of where to look:

■ TheFramework Services Manual covers the TME 10 Framework,including the CORBA architecture and the IDL.

■ TheApplication Services Manual discusses the TME 10 ADEapplication services, including transactions, exceptions,notification, scheduling, and CCMS.

Page 11: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Preface

Application Development with TME 10 ADE vii

■ TheDesktop Services Manual provides in-depth informationabout the TME 10 ADE Desktop services.

■ TheProgrammer’s Reference Manuals provide reference pagesfor the interfaces, operations, and functions that make up theTME 10 ADE Application Programming Interface (API).

What This Guide ContainsApplication Development with TME 10 ADEcontains the followingchapters:

■ Chapter 1, “Anatomy of a TME 10 ADE Application”Discusses how to approach the design of a TME 10 application.Includes discussion of design issues that are unique to distributedapplications.

■ Chapter 2, “Defining an Application with IDL”Provides an overview of the Interface Definition Language(IDL), method execution styles, and inheritance concepts.

■ Chapter 3, “Method Implementations”Describes how to use the TME 10 ADE application services toimplement application methods.

■ Chapter 4, “Implementations for CCMS Methods”Describes the CCMS methods for which an application mustprovide implementations. Includes a discussion ofimplementation overrides.

■ Chapter 5, “Creating Scalable Operations”Discusses application scalability. Covers the use of theInter-Object Message (IOM) service and iterator-based methods.

■ Chapter 6, “Profile Endpoint Methods”Describes the implementation of the methods for a profileendpoint class.

■ Chapter 7, “Creating an Application User Interface”Discusses how to use the TME 10 Desktop Services to create agraphical interface for your application.

Page 12: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Preface

viii Version 3.6

■ Chapter 8, “Writing Client Programs”Describes how to implement stand-alone programs that act asclients of objects in TME 10.

■ Appendix A, "Tivoli/Phone Build Environment"Describes the structure of the Tivoli/Phone sample buildenvironment.

Conventions Used in This GuideThe guide uses several typeface conventions for special terms andactions. These conventions have the following meaning:

Bold Commands, keywords, file names, or otherinformation that you must use literally appear inbold.Names of windows, dialogs, and other controls alsoappear inbold.

Italics Variables and values that you must provide appear initalics.

Bold Italics New terms appear in bold italics when they are definedin the text.

Monospace Code examples appear in amonospace font.

Many procedures in this guide include icons in the left margin. Theseicons provide context for performing a step within a procedure. Forexample, if you start a procedure by double-clicking on a policy regionicon, that icon appears in the left margin next to the first step. If thefourth step of the procedure instructs you to open another icon, thaticon appears in the left margin next to the fourth step.

Page 13: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Preface

Application Development with TME 10 ADE ix

Platform-specific InformationThe following table identifies text used to indicate platform-specificinformation or procedures.

Platform Supported Versions

AIX 4.x Managed Node, Endpoint:IBM RS/6000 series running AIX, Versions 4.1, 4.2,and 4.3

AS/400 Endpoint:V3R2, V3R7, V4R1, and V4R2

Digital UNIX Managed Node, Endpoint:Versions 4.0a and 4.0d.

DG/UX Endpoint:Versions 4.11 and 4.20 on the ix86 platform

HP-UX Managed Node, Endpoint:HP9000/700 and 800 series running HP-UX, Versions10.01, 10.10, 10.20 and 11.00

NCR Managed Node, Endpoint:NCR 3000 series running NCR UNIX SVR4 MP-RAS3.0.1 and 3.0.2

NetWare PC Agent or Endpoint:IBM-compatible PCs 486 or higher running NovellNetWare, Versions 3.11, 3.12, 4.01, 4.1, and 4.11

OS/2 TME 10 Desktop for Windows, PC Agent, or Endpoint:IBM-compatible PCs 486 or higher running IBM OS/2,Versions 2.0, 2.1,Warp 3.0, and Warp 4.0 withWin-OS/2

Pyramid Endpoint:Pyramid MIServer-ES, Version 5.4MN

Sequent Managed Node, Endpoint:Sequent DYNIX/ptx, Releases 4.2.3 and 4.4.2

Page 14: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Preface

x Version 3.6

User and Group IconsThe following icons represent the user and group profiles resources:

User and group profile resources are created in the context of a profilemanager. After the initial distribution of a user or group profile, theprofile icon appears in the view dialog of subscribers. Subscribers canbe profile managers, hosts, or NIS domains.

SCO Managed Node, Endpoint:SCO UnixWare 7, SCO UnixWare Versions 2.1.1 and2.1.2

SGI Managed Node, Endpoint:SGI IRIX, Versions 6.2 and 6.4

Solaris Managed Node, Endpoint:Sun SPARC series running Solaris, Versions 2.4, 2.5,2.5.1, and 2.6

Solaris Intel Managed Node, Endpoint:Solaris2-ix86, Versions 2.5.1 and 2.6

SunOS Managed Node, Endpoint:Sun SPARC series running SunOS, Versions 4.1.3 and4.1.4

Windows TME 10 Desktop for Windows, PC Agent, or Endpoint:IBM-compatible PCs 486 or higher running MicrosoftWindows, Versions 3.1, 3.11, and Windows 95

Windows NT TME 10 Desktop for Windows, PC Agent, ManagedNode, or Endpoint:IBM-compatible PCs 486 or higher running MicrosoftWindows NT, Versions 3.51 SP5, 4.0, and 4.0 SP3.

Platform Supported Versions

Page 15: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Preface

Application Development with TME 10 ADE xi

Contacting Customer SupportIf you encounter difficulties with any Tivoli products, you can enterhttp://www.support.tivoli.com to view the Tivoli Support home page.After you link to and submit the customer registration form, you willbe able to access many customer support services on the Web.

Use the following phone numbers to contact customer support in theUnited States: the Tivoli number is 1-800-848-6548 (1-800-TIVOLI8)and the IBM number is 1-800-237-5511 (press or say 8 after you reachthis number). Both of these numbers direct your call to the TivoliCustomer Support Call Center.

We are very interested in hearing from you about your experience withTivoli products and documentation. We welcome your suggestions forimprovements. If you have comments or suggestions about thisdocumentation, please send e-mail to [email protected].

Page 16: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Preface

xii Version 3.6

Page 17: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Development with TME 10 ADE 1–1

Anatom

y of a TM

E 10 A

DE

Application

1Anatomy of a TME 10 ADEApplication

All the examples in this book relate to the sample application,Tivoli/Phone. This chapter provides the information you need to installthe Tivoli/Phone application in your TME 10 environment. Thischapter also contains a procedure to install the source code for theapplication on your machine.

Introduction to Tivoli/PhoneThis sample application was originally written with the ManagedNode as the endpoint. For the 3.2 version of TME 10 ADE, this sampleapplication was ported to enable it to work with LCF endpoints as wellas Managed Node endpoints. Throughout this manual, you will noticereferences to both Managed Node and LCF endpoints. Where you seereferences to theManagedNode object, the application has now beenported to work with theEndpoint object as well.

Before you begin, it is important that you understand the basics of thethe lightweight client framework (LCF), the type of endpoint itsupports, and how this type of endpoint differs from the ManagedNode as an endpoint. For more information about LCF, seeApplication Development for the Lightweight Client Framework. It isimportant that you understand the difference between Managed Nodeand LCF endpoints before you begin using this manual.

1

Page 18: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Installation

1–2 Version 3.6

InstallationThe Tivoli/Phone application and source code are both installed as partof installing TME 10 ADE. To make the application and sourceavailable, you do not need to perform any steps beyond installing TME10 ADE.

For instructions on how to install TME 10 ADE, see the installationchapter in the Introduction to TME 10 ADE.

Introduction to Object-oriented ApplicationsAn object-oriented application is a set of objects that interact with oneanother. Each object comprises a set of functionality that defines anapplication component. Objects interact through a client/server modelwhere one object (client) requests an operation from another object(server). Each class of object defines a set of operations to which anobject of that class can respond. The set of operations is called aninterface.

There are two advantages to an object-based application. First, you cancreate application components that can be reused in other applicationswith little or no extra code. If you take the time up front to design andimplement reusable classes of objects, you can reduce developmenttime and maintenance costs of new applications.

Object-oriented applications are also very useful in a distributedenvironment like TME 10, where application components can bespread across a network. In TME 10, an object can request anoperation on another object, regardless of where the other objectresides. The TME 10 Object Request Broker (ORB) is responsible forlocating the server object and passing it the client’s request.

This chapter provides a quick introduction to application developmentin TME 10 ADE and focuses on the special design issues a TME 10ADE developer can face. Although this chapter does touch on someconcepts of object-oriented design, it is not intended as a completeprimer. This chapter also assumes that you have read the first twochapters in theIntroduction to TME 10 ADE, which provide a goodoverview of the TME 10 environment.

Page 19: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

TME 10 ADE Development Cycle

Application Development with TME 10 ADE 1–3

Anatom

y of a TM

E 10 A

DE

Application

TME 10 ADE Development CycleAlthough there are many ways to design an application,object-oriented applications are best suited to an incremental,bottom-up approach. The first step is to analyze the problem andconstruct an application model. From this model, you can break theapplication into individual components that can be modelled as objectclasses.

Next, you must define the behavior of each class of object. Thisincludes the data the class encapsulates as well as the interfaces (set ofoperations) that it supports. The CORBA specification defines anInterface Definition Language (IDL) to help you define your classes.IDL is a declarative language that expresses inheritance and interfacesindependent of the language in which you implement the object. TME10 ADE provides an IDL compiler that takes an IDL specification andgenerates code for the client and server portions of each operation.

The next step in the development process is to provideimplementations for all the operations that a component supports. TheIDL compiler generates an implementation template for eachoperation that you define. To implement an operation, you must fill in

Analyze Problem

Identify Components

Create IDL

Implement Component

Integrate Components

Test Component

Page 20: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Analysis and Design

1–4 Version 3.6

the template with code. Currently, TME 10 ADE only creates C orshell versions of the implementation templates.

Since application components encapsulate a set of functionality, itshould be possible to implement and test each component separately.Further, components and their clients can be developed concurrently,since the component has a well-defined interface established early inthe development cycle.

When enough components have been implemented and tested, you canintegrate the components to construct the application. Testing at thisstage should require less effort, since each component has beenvalidated separately.

Application Analysis and DesignThe remainder of this book will deal with the design andimplementation of a sample TME 10 ADE application. Thisapplication, called Tivoli/Phone, tackles one of the thorniest issuesfacing business today: the corporate phone list. With the upsizing anddownsizing and right-sizing common in today’s corporations, theaccuracy of a company phone list can take quite a beating. In addition,an administrative staff can expend a great deal of effort (and paper)updating and issuing new directories.

Although there are numerous methods for analyzing systems anddesigning object-oriented applications, we will restrict ourselves to aninformal analysis of our business problem. It is beyond the scope ofthis book to try and recommend the best object analysis/design system,since each system has advantages and disadvantages depending on thetype of application. Also, the most common object-oriented analysismethods do not currently lend themselves to modelling distributedobject systems. For example, few of the common notations for objectanalysis include the ability to denote the “location” of an object. In thisbook, the best we can do is discuss some of the requirements anddesign issues that are important in a distributed environment.

Page 21: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Analysis and Design

Application Development with TME 10 ADE 1–5

Anatom

y of a TM

E 10 A

DE

Application

Problem AnalysisFrom a business process standpoint, the maintenance of the corporatephone list could be easily integrated with a larger, more generalpersonnel process. For example, when a new employee joins thecompany, the phone list could be updated as part of the process ofassigning office space and a telephone.

As a first step toward integrating the phone list into the businessprocess, we will design an on-line phone list that can be maintained ata single source and distributed to each department in the company. Thefigure below is a simplified data flow diagram of the phone listapplication.

Organizationally, we will maintain the corporate phone list in adatabase, with each record representing anentry in the phone list.Since this application manages a phone list, each record will containthe name and phone number of a person, plus any extra demographicinformation that is useful.

■ Name

■ Phone number

■ Address

Phone ListDatabase

AddEntry

New Employee

Entry

UpdateEntry

Change/Delete

Entry

Distribute

Entries

Entries

Find/Query

Entries

Request

Report

Page 22: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Analysis and Design

1–6 Version 3.6

■ City

■ State or province

■ Country

■ Postal code

■ Type of phone (home, business, fax, pager, etc.)

■ Owner of phone (internal, customer, vendor, etc.)

■ Descriptive comment

Each record in the database also requires a unique key. For theTivoli/Phone application, there is no single field that we can guaranteewill be unique. We can probably guarantee unique name/phone pairs,however, so we can use a concatenation of these two fields as therecord key.

The database in our application responds to several operations, such asAdd Entry , Update Entry, andFind/Query. We also define anoperation calledDistribute that sends the contents of the phone listdatabase to the various department members.

We will assume that when the members receive the phone list, theywill import it into their on-line personal organizer applications. Whenthe phone list reaches the department members, the application mustconvert the database into a file that the employees can import into theirpersonal organizer.

We will expand on the set of operations that the Tivoli/Phoneapplication supports later in this chapter when we define the databaseobject’s interface.

Phone ListDatabase

Department Members

Distribute

Page 23: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Analysis and Design

Application Development with TME 10 ADE 1–7

Anatom

y of a TM

E 10 A

DE

Application

The Profile Object ModelIt may seem that we are cheating somewhat, since our analysis of theapplication requirements fits very well with the TME 10 Configurationand Change Management System (CCMS) paradigm. In this model,application information is maintained in a central database called aprofile. Other resources, calledprofile endpoints, subscribe to receivethe information in the profile database. For a complete discussion ofCCMS, see theApplication Services Manual, Vol. II.

In the workflow diagram of the Tivoli/Phone application, the phonelist database corresponds to a profile, the department members toprofile endpoints.

Although it is by no means true that the profile paradigm is suitable forall applications, it does suit the requirements of our phone listapplication. Generally speaking, the profile paradigm is very usefulwhen application requirements meet the following criteria:

■ The application data can be represented as discrete data elements(records).

■ The data flow can be modelled as a hierarchy, originating at acentral point and cascading to lower points in the hierarchy.

■ The lowest points (endpoints) of the hierarchy correspond tosystem resources, such as NIS domains or Managed Nodes.

■ The application allows or requires the application data to beedited at each level in the hierarchy.

■ The data does not vary widely between endpoints.

If your application requirements match the above criteria, there issignificant advantage to using the profile paradigm. As mentionedearlier, the Tivoli/Phone’s database corresponds to a profile and thedepartment members to endpoints. Using profiles simplifies theinteraction between the application components, since CCMSmanages much of the interaction between profiles and endpoints. Ifyou use some other object model, you must define and manage theobject relationships explicitly.

Page 24: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Analysis and Design

1–8 Version 3.6

Identifying Classes and OperationsAfter you have modelled your application (either using a standardobject notation such as Booch, or using the more homespun method wehave used), the next step is to identify the classes in your applicationand the operations they support.

Looking at the data hierarchy diagram above, it is readily apparent thatthere are two classes of objects in the Tivoli/Phone application: thephone list database and the department members. Since thisapplication fits into the profile object model, we can even go furtherand map these classes onto classes defined by CCMS:

■ Phone list database — configuration profile

■ Department members — profile endpoints

The Profile Class

Since we have chosen to use the TME 10 ADE profile paradigm, wemust define a profile-based class to represent our phone listinformation. We will call this classPhoneListProfile. To define ourclass, we must identify theinterfaces the class will support. Aninterface is a collection of operations and attributes that areimplemented by a class. Interfaces can inherit other interfaces, so youcan build aggregate sets of operations through inheritance.

For the Tivoli/Phone application, we will define aPhoneListProfileinterface that thePhoneListProfile class will implement. ThePhoneListProfile interface must support operations for the following:

■ Basic profile behavior

■ Behavior specific to aPhoneListProfile profile

Phone ListDatabase

Department Members

Distribute

Page 25: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Analysis and Design

Application Development with TME 10 ADE 1–9

Anatom

y of a TM

E 10 A

DE

Application

■ An application user interface

Since TME 10 ADE defines the basic behavior of profiles, it providesan interface that contains the minimum set of attributes and operationsthat a profile object requires. Your application’s interface can inheritthis interface, which is calledTMF_CCMS::Profile . Later, when youimplement the application’s operations, you can choose to inherit thestandard implementations for theProfile operations, or create yourown.

In addition to the basic behavior, we must identify any operations thatare specific to the phone profile. A good way to identify requiredoperations is to examine the data flow model of your application.

Interface NotationIn TME 10 ADE, sets of related interfaces are grouped intomodules.Modules also provide scoping for interfaces to avoid name clashes.Interfaces are usually refered to using the form:

module::interface

For example, theTMF_CCMS::Profile interface refers to theProfile interface defined in theTMF_CCMS module.

The module is often omitted in this book, whenever it is obvious orunimportant which module contains the interface or operation.

Page 26: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Analysis and Design

1–10 Version 3.6

Elements of the diagram that appear as verbs are good candidates foroperations or types of operations.

From the diagram for Tivoli/Phone, we can identify three main groupsof operations (theDistribute operation is part of the basic profilebehavior):

■ Adding entries

■ Updating existing entries (includes editing and deleting)

■ Finding entries

Breaking down these categories further, we can construct a fairlycomplete list of operations for thePhoneListProfile interface:

Operation Name

Add entries create_phone_entrycreate_entries

Update entries modify_phone_entry

Delete entries delete_phone_entrydelete_phone_entries

Phone ListDatabase

AddEntry

New Employee

Entry

UpdateEntry

Change/Delete

Entry

Distribute

Entries

Entries

Find/Query

Entries

Request

Report

Page 27: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Analysis and Design

Application Development with TME 10 ADE 1–11

Anatom

y of a TM

E 10 A

DE

Application

Theget_all_entries andfind_by_name operations have something incommon: they have the ability to return arbitrarily large amounts ofdata. To solve potential scalability problems, Tivoli/Phone implementsthese operations using a concept callediteration. Iterator-basedmethods return large amounts of data as a series of small chunks.Iteration is described in more detail on page 1-18 and in Chapter 5,“Creating Scalable Operations.” The reason this is important in thedesign phase is that Tivoli/Phone defines an interface calledPhoneListIterator that contains operations to support iterator-basedoperations. ThePhoneListProfile inherits this interface.

Retrieve entries get_phone_entryget_phone_entries

Retrieve all entries get_all_entries

Search for a name find_by_name

List all names list_phone_entries

Operation Name

TMF_CCMS::Profile

PhoneListProfile

PhoneListIterator

— Defined by TME 10 ADE

LCF Endpoints Have No GUILCF endpoints do not have a graphical user interface (GUI).Discussions here of the user interface for Tivoli/Phone refer only toManaged Node endpoints. The part of the Tivoli/Phone source code thatsupports the application GUI is unchanged from previous versions.

Page 28: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Analysis and Design

1–12 Version 3.6

Since the Tivoli/Phone application will have a user interface, thePhoneListProfile interface must support operations to launch andmanage the GUI. We can define an operation, calledui_phone_props,that starts the application GUI. Tivoli/Phone places theui_phone_propsoperation in an interface calledPhoneEntryGUI.ThePhoneListProfile interface inherits from thePhoneEntryGUIinterface.

Encapsulating the GUI-related operations minimizes the impact ofpossible future changes. Changing the user interface supported byPhoneListProfile only requires that you change what it inherits, ratherthan requiring you to extract all GUI-related operations from theinterface.

The Endpoint Class

The second class of object that we identified in the Tivoli/Phoneapplication model represents the department members. Since we havechosen the profile paradigm for our application, this class translates toa profile endpoint. We will call this classPhoneEndpoint. The classhas several functional requirements:

1. It must be able to subscribe to receive phone list updates (basicprofile endpoint behavior).

2. It must be able to convert a phone list database into a file that canbe imported into a personal organizer application.

TMF_CCMS::Profile

PhoneListProfile

PhoneListIterator

PhoneEntryGUI

— Defined by TME 10 ADE

Page 29: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Analysis and Design

Application Development with TME 10 ADE 1–13

Anatom

y of a TM

E 10 A

DE

Application

3. It must be able to import a file from a personal organizerapplication into a phone list database. This behavior is called“populating” a profile.

To satisfy the last two behavior requirements, we will define aninterface calledplbo (for phone list behaviorobject). ThePhoneEndpoint class implements this interface. Theplbo interfacehas two operations.

To satisfy the first requirement, the standard way to pick up basicprofile endpoint behavior is to inherit fromTMF_CCMS::ProfileEndpoint . Later, when you install or run theapplication, thewinstendpt command, described in Chapter 6,“Profile Endpoint Methods,” installs the behavior on theManagedNode or Endpoint object. After you add thePhoneEndpointclass behavior to theManagedNode or Endpointclass, those objects then have access to the methods and attributes ofthe application’s class.

Task Operation

Convert database to file update_phone

Convert file to database discover_phonelist

How to Add Behavior to the Endpoint ClassFor Tivoli/Phone, the scriptsample_app.initexecuteswinstendpt and adds the endpoint behavior to theEndpointclass.sample_app.init is described in “InstallationSpecification” on page 2-28.

Page 30: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Design Issues in TME 10 ADE Applications

1–14 Version 3.6

Design Issues in TME 10 ADE ApplicationsDistributed object environments present a set of design challenges toan application developer; some age-old, some new. In addition, manyof the TME 10 ADE services, such as exceptions, require thoughtduring the design phase if you want to avoid problems later in theimplementation. This section examines several of these design issuesand how they affect the design or implementation of a TME 10 ADEapplication.

TransactionsTME 10 ADE provides a transaction service for servers and ManagedNodes that allows you to combine multiple operations into a singlecoherent unit. However, LCF endpoints do not support transactionsbecause there is no database on this type of endpoint.

SecurityApplications that run in a distributed, multi-user environment facespecial security problems. For example, an application user on onemachine must be able to invoke operations on application objects,even if they reside on a machine where the user does not have anaccount.

There are two types of security in TME 10: authentication andauthorization. Authentication is the process of verifying that a user orservice is really what it says it is. Authorization is the process ofensuring that the user is allowed to perform a given operation. TME 10automatically handles authentication of application users. Yourapplication, however, must handle authorizing a user’s right to invokeyour application’s operations.

An application enforces authorization rules throughaccess controllists (ACLs). An access control list defines the roles that a user musthave to invoke an operation. Roles are arbitrary names assigned todifferent levels of access. TME 10 defines the following authorizationroles:super, senior, admin, anduser. These roles are simplypre-defined names that you can use. It is up to your application tointerpret the meaning of each role. You can implement these roles as ahierarchy (for example,senior impliessenior, admin, oruser), but it

Page 31: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Design Issues in TME 10 ADE Applications

Application Development with TME 10 ADE 1–15

Anatom

y of a TM

E 10 A

DE

Application

is not required. You can even define your own custom roles to augmentor replace the standard TME 10 roles. See theApplication ServicesManual, Vol. II, for information about defining custom roles.

You create access control lists for your application’s operations whenyou create the application’s IDL definition. It can be helpful, however,to define the roles required by each operation ahead of time. Creatinga “map” of your application’s operations and their corresponding rolescan help you spot holes in your security model.

Since the Tivoli/Phone application is relatively simple, we do not needto create any new authorization roles; we will use the ones provided byTME 10. The Tivoli/Phone application uses the following rules toassign roles to its operations:

■ Operations that modify the behavior of the TME 10 installationrequire thesuper role.

■ Operations that manipulate an object’s characteristics (changingpolicy, deleting) require thesuper or senior role.

■ Operations that manipulate an object’s state (such as changingrecords in a profile database) require thesuper, senior, or adminrole.

■ Read-only operations require thesuper, senior, admin, or userrole.

Custom Application RolesAlthough Tivoli/Phone does not define custom roles, it is often a goodstrategy to use application-specific roles in place of the TME 10super,senior, admin, anduser roles.

For example, an operation that would require the TME 10senior rolewould instead require thephone_senior role. Overlaying customroles gives an administrator the flexibility to assign high-level roles inan application without necessarily assigning corresponding roles inTME 10.

Page 32: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Design Issues in TME 10 ADE Applications

1–16 Version 3.6

A simple authorization chart for operations of thePhoneListProfileinterface is shown below.

When you create your authorization map, you must not only thinkabout each operation, but also about any other operations it mightinvoke. It does not make any sense, for example, to assign theadminrole tomodify_entry if modify_entry invokes operations that requirea different role. Anadmin user could invoke the operation, but itwould fail because it could not invoke the sub-operations.

Another security-related issue that you must consider is the privilegeof operations. An operation’s privilege is the user ID and group ID onwhose behalf the operation runs. Why not just set the operation’sprivilege to the user and group of the user that invokes it? There aretwo situations where that strategy is insufficient:

■ A user must invoke operations on objects that reside on hostswhere the user does not have an account.

■ A user must invoke operations that require another set ofprivileges (such as root).

Operation Required RolesSpecial

Privileges

create_phone_entry admin No

create_entries admin No

modify_phone_entry admin No

delete_phone_entry admin No

delete_phone_entries admin No

get_all_entries admin No

get_phone_entry admin or user No

get_phone_entries admin or user No

list_phone_entries admin or user No

find_by_name admin or user No

Page 33: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Design Issues in TME 10 ADE Applications

Application Development with TME 10 ADE 1–17

Anatom

y of a TM

E 10 A

DE

Application

The first situation is very common in a distributed environment. Anapplication should not require users to have an account everywhere anoperation can be invoked. At the very least, this can causeadministrative difficulties (ensuring everyone has an accounteverywhere they need one). It can also cause security problems byrequiring a user to have an account on a host where he or she wouldnot ordinarily have access.

To solve this problem, TME 10 operations by default run as the UNIXnobody account. Using thenobody account allows a user to invokeoperations on objects that reside on hosts where the user does not havean account. Audit information is not lost, however, since theapplication can still determine which principal (TME 10administrator) invoked the operation.

On NT, TME 10 operations by default run as the accounttmersrvd,which is the NT equivalent of the UNIXnobody account. For LCFendpoints on NT, the default account islcfrsrvd . It is similar totmersrvd except that it does not require the Tivoli AuthenticationPackage (TAP) to be enabled.

Your application might also define operations that require an operationto temporarily increase its privileges. The most common example is anoperation that must write to a system file such as/etc/passwd. Theoperation must be able to run “as root,” regardless of who the user is.Security is maintained by ensuring that the user has the correct role toinvoke the operation.

ExceptionsThe TME 10 ADE exception mechanism has several advantages overtraditional means of error handling. Operations throw exceptions thatcan be caught and dealt with at any point in the call chain, even acrossprocess boundaries.

Although your application’s use of exceptions seems mainly animplementation detail, there are two areas where you must givethought to exceptions during the design phase:

■ New exception types that are unique to an interface.

■ Types of exceptions that each operation can throw.

Page 34: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Design Issues in TME 10 ADE Applications

1–18 Version 3.6

TME 10 ADE provides a wide variety of exception types, but mostcover broad error types (for example, general operation failure orinvalid parameter errors) or system-level errors (permissionsviolation, system call failure). It is a good idea to define new exceptiontypes that allow your operation to throw more specific kinds of errors.For example, thePhoneListProfile interface defines anExPhoneexception. Operations can throw this exception to distinguish betweeninternal application errors and more basic system problems. We willdiscuss the exception types defined by Tivoli/Phone in more detailwhen we look at the IDL specification of its interfaces in the nextchapter.

You must also give thought to the types of exception that eachoperation in your interfaces can throw. Since an exception is a validresponse of an operation to its client, the types of exceptions anoperation can throw are very much a part of an interface definition.Clients that invoke an operation must know what types of exceptionsmight occur and be able to handle them. The IDL specification of aninterface allows you to list the exceptions thrown by each operation.See Chapter 2, “Defining an Application with IDL,” for more details.

ScalabilityWhen you design your application, consider the effect objectinteractions will have in a large installation. For example, an operationthat contacts every node in an installation might seem acceptable for10 or 20 nodes. In a 5,000-node installation, however, such anoperation could take a prohibitive amount of time.

Another consideration is parameter scalability between a client andserver. Passing data between a client and a server is not the same aspassing data between two functions. The client and server can bewidely separated, requiring the data to travel across a network. Tocreate a truly scalable application, you must carefully consider theamount of data that is passed to or returned by an operation.

Page 35: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Design Issues in TME 10 ADE Applications

Application Development with TME 10 ADE 1–19

Anatom

y of a TM

E 10 A

DE

Application

The memory requirements of an operation are not always immediatelyobvious. Consider an operation that takes a 100-byte record as aparameter.

For each 100-byte record passed between the client and server,approximately 500 bytes of total memory are used. The client has acopy of the record, which it passes to the client stub. The client stubcopies the record and encodes it for transmission, which enlarges it toapproximately 150 bytes. The stub transmits the encoded record to theserver skeleton which decodes the record and passes it to the serverimplementation. Passing a sequence of 5,000 records to the serverwould require 2.5MB of memory (1.25MB on the client and servereach) and would push 750Kb of data across the network.

How can you plan for data scalability? Design your application’soperations to reduce the chance of receiving or returning unboundedsequences of data. If an operation is likely to be called on to process alarge amount of data, consider not accepting the data as a parameter.Instead, use an inter-object message (IOM) channel to pass the databetween the client and the server. An IOM channel is a direct socketconnection between a client and a server.

Operations that can potentially return an unbounded amount of datashould use a mechanism callediteration to return the data in a seriesof manageable chunks. When a client invokes an iterator-based

Server(100 bytes)

ClientStub

ServerSkeleton

EncodedRecord(150 bytes)

150 bytes

EncodedRecord(150 bytes)

Client(100 bytes)

Page 36: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Design Issues in TME 10 ADE Applications

1–20 Version 3.6

operation, the operation only returns the firstn elements of thesequence (wheren is determined by the application). The operationalso returns aniterator handle, which the client can use to retrievesubsequent chunks of the sequence. The client processes each block ofdata and fetches the next until all the elements have been processed.The Tivoli/Phone application includes examples of iterator-basedmethod from both a client and a server point of view.

Chapter 5, “Creating Scalable Operations,” discusses the details ofimplementing scalable methods with iterators and IOM channels.

Customizations and ExtensibilityWhen you design an application, you must decide how much latitudeyou want to allow for adding custom features. For example, most TME10 ADE applications allow you to set custom default and validationpolicy for various application components.

Many applications also support more extensive customization throughthe TME 10 Application Extension Facility (TME 10 AEF) toolkit.TME 10 AEF allows a user to extend an existing application in anumber of ways:

■ Add fields and controls to application dialog

■ Create callback methods that service the custom controls

■ Add attributes to objects and profile records

■ Define custom actions that execute before or after distribution ofa profile

■ Customize application icons and bitmaps

If you want your application to support extensibility through TME 10AEF, you must implement your operations to accommodate usercustomizations.

Page 37: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Design Issues in TME 10 ADE Applications

Application Development with TME 10 ADE 1–21

Anatom

y of a TM

E 10 A

DE

Application

InternationalizationAs the international software market grows larger, so will the drive toprovide a wide variety of applications in users’ native languages. Tocreate an application that can support a variety of languages, you musttake the time to remove the English-language bias from yourapplication. If your TME 10 ADE application must support multiplelanguage environments, you will need to take the following ideas intoaccount:

■ Language-dependent text must be made external to theapplication. Messages, labels, and strings that are traditionallyhard-coded English text must be stored in a language-neutralformat and translated into the appropriate language at run-time.

■ Cultural conventions, such as date and monetary formats,must be taken into account. Your application should avoidstoring this kind of information in a language-dependent formatif you intend to support multiple languages.

■ Your application might be required to support languages thatare not covered by the ASCII character set. You should avoidmaking comparisons that assume implicit ASCII values (forexample, statements such asx == ‘A’ ).

■ Different languages use different rules for collating(alphabetizing) characters. Your application should avoidusing functions, such asstrcmp, that assume an English locale.

■ Many languages differ from the left-to-right, top-to-bottomorientation of English. When you are laying out yourapplication’s dialogs, keep in mind that the placement of gadgetscan affect the ability to translate the application into a differentlanguage.

To help you create international applications, TME 10 ADE providesa message catalog system. Message catalogs allow you to place all theconstant messages and strings of an application into external files. Youcan then translate the message catalog into different languages. Whenthe application must display a message, it consults the user’slocaleand displays the appropriate message. A locale specifies the language,character set, monetary formats, and date formats that define a

Page 38: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Summary

1–22 Version 3.6

language environment. For example, your application might supportan English locale, a French locale, and a German locale.

The TME message catalog facility is based on the X/Open messagecatalog facility. In that case, why not use the X/Open API directlyinstead of the TME 10 ADE API? Not all architectures support theX/Open message catalog API. Using the TME 10 API allows forimplementation on systems that do not support the X/Open model.

The Tivoli/Phone application makes extensive use of messagecatalogs. You will see numerous examples of using message catalogsas you read about the implementation of the Tivoli/Phone application.You can also find a complete discussion of message catalogs in theApplication Services Manual, Vol. I.

SummaryThis chapter introduced a simple approach for beginning to analyzeand design a TME 10 ADE application. In this approach, you break anapplication into components that correspond to classes in an objectmodel. Then, for each component, you must define the operations towhich the component responds. Encapsulating applicationfunctionality in a set of object components gives you the ability toimplement and test components in parallel. You can then integrate thecomponents to create the application.

The chapter also introduced a sample TME 10 ADE application calledTivoli/Phone. The design and implementation of the Tivoli/Phoneapplication—a phone list distribution system—will be the basis of theremainder of this book.

Finally, this chapter gave an overview of some design issues that youmust consider when creating a TME 10 ADE application. Some issues,such as security and scalability, are general to any distributedapplication. Others, such as support for TME 10 AEF and the use ofexceptions are specific to TME 10 ADE.

In the next chapter, we will move from an abstract definition ofTivoli/Phone to a more concrete design and finally to an IDLspecification for the application.

Page 39: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Development with TME 10 ADE 2–1

Defining an A

pplicationw

ith IDL

2Defining an Application with IDL

After you create an object diagram for your application, the next stepis to create a programmatic definition of the application using theTivoli Extended Interface Definition Language (TEIDL). TEIDL is anextension of the Interface Definition Language called for in theCORBA specification. With TEIDL you describe your application’sobjects in various ways, from an abstract definition of the interfacesand operations to the commands that are executed when a class isinstalled in TME 10. There are four parts to a TEIDL description:

■ Interface definition

■ Implementation specification

■ Program specification

■ Installation specification

The interface definition specifies the interfaces and operationssupported by the objects in your application. The implementationspecification details the classes and methods that will implement theinterfaces and operations. The program specification refines theimplementation specification by defining the execution characteristicsof each method. Finally, the installation specification controls how theapplication’s classes behave when they are installed in a TME 10installation.

After you create the TEIDL description of your application, you canuse the TME 10 ADE IDL compiler to generate source code from thedescription. The compiler generates code to handle method requests

2

Page 40: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Interface Definition

2–2 Version 3.6

and data marshalling between the client and the ORB and between theORB and the method server (client stubs and server skeletons). Thecompiler also generates method implementation templates. You mustfill in the method templates to implement the methods.

Interface DefinitionThe interface definition uses IDL to construct a high-level definitionof your application and its objects. IDL allows you to define yourapplication in terms independent from the language in which it will beimplemented. In the interface definition, you define the followinginformation about your application:

■ New data types, such as structures and enumerated types thatyour application’s interfaces require

■ New types of exceptions that operations in your application canraise

■ The interfaces supported by your application’s objects

■ The inheritance relationship between interfaces

■ The attributes and operations that compose each interface

IDL Data TypesOperations defined in IDL often have parameters or return values thathave complex data types. IDL provides a way to define complex datatypes, such as structures and enumerated data types as part of yourinterface definition.

The Tivoli/Phone application defines several new data types for use bythe application’s operations. The most significant of these data types isa structure calledPhoneEntryInfo. The structure maintains the valuesof a single entry’s attributes, as well as certain state information. Alloperations defined by thePhoneListProfile interface usePhoneEntryInfo structures when passing or returning a phone listentry. The IDL definition of thePhoneEntryInfo data type is shownbelow.

struct PhoneEntryInfo { unsigned long flags; boolean fixed;

Page 41: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Interface Definition

Application Development with TME 10 ADE 2–3

Defining an A

pplicationw

ith IDL

boolean read_only; string name; string phone; PhoneOwner owner; PhoneType type; string address; string city; string state; string country; string postal; string comment; AEFAttrList aef_attrs;};

The syntax of the definition is similar to C, except that simple datatypes, such asstring, are denoted in a language- independent way. TheTEIDL compiler supplied with TME 10 ADE maps the IDL data typesinto language-specific form at compile time. So, the IDLstring datatype, for example, is converted to achar * if you choose to create anANSI C binding for the IDL.

Theowner andtype fields of thePhoneEntryInfo structure areenumerated data types that are also part of the Tivoli/Phone interfacespecification.

enum PhoneOwner { internal, customer, vendor, personal };enum PhoneType { home, business, fax, modem, pager };

The interface definition for Tivoli/Phone also defines a data type thatis a sequence ofPhoneEntryInfo structures.

typedef sequence <PhoneEndInfo> PhoneEntryInfoList;

A sequence is a one-dimensional array of elements. The CORBAspecification defines the sequence data type for operations that acceptor return a set of data structures. TME 10 ADE implements thesequence data type and provides a set of C convenience routines formanipulating sequence elements. TME 10 ADE provides a library offunctions for manipulating sequences. See theApplication ServicesManual, Vol. I, for more information.

Page 42: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Interface Definition

2–4 Version 3.6

Exception DeclarationsYou can define your own exception types in IDL. The syntax of anexception definition is shown below.

exception name : parent { arg1, ... argn;};

Thename parameter is the name of the new exception type. Theparentparameter specifies an exception from which the new exception type isderived.

The body of the exception block defines the parameters of theexception. You can use the exception parameters to return informationabout the error that caused the exception. Exceptions inherit theparameters of their parents, so your exception definition only needs toinclude additional parameters specific to that exception type.

The Tivoli/Phone application defines three exception types that theoperations ofPhoneListProfile can throw. The first exception is theExPhoneError exception. This exception is derived from the Tivolibase exception type,ExException.

exception ExPhoneError : SysAdminException::ExException {};

From theExPhoneError type, we derive two more exceptions:ExPhoneError1 andExPhoneError2. These exception types allowthe thrower to pass one or twostring parameters with the exception,respectively.

exception ExPhoneError1 : ExPhoneError { string arg;};

exception ExPhoneError2 : ExPhoneError { string arg1; string arg2;};

There are two drawbacks to the exceptions above. First, you arerestricted tostring parameters. If you have an exception that requiresa singleboolean argument, you must define another exception type.

Page 43: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Interface Definition

Application Development with TME 10 ADE 2–5

Defining an A

pplicationw

ith IDL

Second, you must define a separate exception for each number ofarguments you want to pass. So,ExPhoneError1 takes one argument,ExPhoneError2 takes two arguments, and so on. A more generalexception definition would take a single argument that had theanydata type. Theany data type provides a way to pass a value and specifythe type at run-time. See theFramework Services Manual for specificinformation on how to use theany data type.

exception ExPhoneData : ExPhoneError { any data;};

The code fragment above defines an exception calledExPhoneData.This exception derives fromExPhoneError and takes a singleanyparameter. An operation that throwsExPhoneData must define thevalue and type of the parameter at run-time.

Why derive these exceptions from theExPhoneError exceptioninstead of the base Tivoli exception class? TME 10 ADE allows youto trap groups of related exceptions. A singleCatch statement can trapan exception type, or any exception type that derives from that type.

Try { ...}Catch(ExPhone, ex) { /* Handle a phone application exception */}EndTry;

TheCatch statement above is sufficient to trap any of the Tivoli/Phoneexception types, since they all derive fromExPhone. This conceptworks not only for the exception’s immediate parent, but for any of itsancestors. Since all TME 10 ADE exceptions ultimately derive fromExException, trappingExException is an excellent way to preventunexpected exception types from “leaking through” a catch point.

Try { ...}Catch(ExPhone, ex) { /* Handle a phone application exception */}Catch(ExException, ex) { /* Handle other, unexpected exception types */

Page 44: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Interface Definition

2–6 Version 3.6

}EndTry;

When you design your application’s interface, consider how and whereyour exceptions will be used, and construct exception hierarchies toleverage relationships between exceptions.

Specifying InterfacesThe heart of the interface definition is the definition of the interfacesand their operations. There are three parts to an interface definition:

■ The list of interfaces from which the interface inherits

■ The operations supported by the interface

■ Attributes that are part of the interface

For each operation in an interface, you must define the operation’ssignature. An operation’s IDL signature looks similar to a normal Cprototype: it defines the parameters of the operation and the type ofdata that it can return. The major difference in an IDL signature is thatyou must specify how the operation uses each parameter. A parametercan be used as an input parameter, and output parameter, or both. Youmust include the appropriate keyword in front of each parameter.

void get_phone_entry(in string key, out PhoneEntryInfo entry);

The code excerpt above shows the IDL signature of theget_phone_entry operation. The operation takes two parameters: aninput string parameter calledkey and an output parameter calledentry.Parameters that can be used for both input and output are specifiedwith the keywordinout.

To provide a complete definition of an operation, you should alsoinclude the types of exceptions that the operation can throw. Everyoperation signature can contain araises block that lists the possibleexceptions raised by the operation.

boolean next_entries( in long how_many, out PhoneEntryInfoList entry_list) raises(ExPhoneError,SysAdminException::ExInvalid);

Page 45: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Interface Definition

Application Development with TME 10 ADE 2–7

Defining an A

pplicationw

ith IDL

Thenext_entries operation shown above can raise theExPhoneErrorexception or the system-definedExInvalid exception. TME 10 ADEdoes not actually restrict an implementation of an operation to theexceptions listed in its signatures. It is simply a good practice toenumerate the exceptions in the interface definition. A developerwriting a client must know which exceptions to trap without lookingat the implementation of each operation. Consider the specification ofexception types to be part of the documentation of an interface.

In addition to operations, an interface definition can have attributes.Any object that supports an interface must support the interface’sattributes. How the object interprets the attribute is left to the objectimplementation. Although the Tivoli/Phone interfaces do not defineattributes, thePhoneListProfile interface does inherit severalattributes from theTMF_CCMS::Profile interface.

PhoneListProfile Interface Definition

Recalling Chapter 1, “Anatomy of a TME 10 ADE Application,” thedesign for Tivoli/Phone comprised two major interfaces: thePhoneListProfile interface and theplbo interface.PhoneListProfilesupports operations to deal with entries in the phone list database. Theplbo interface supports operations required by the objects thatsubscribe to receive updated phone lists.

Page 46: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Interface Definition

2–8 Version 3.6

In Chapter 1, we defined thePhoneListProfile interface to comprise aset of basic operations plus a set of inherited operations. Theinheritance tree of the interface is shown below.

As you can see from the diagram,PhoneListProfile inherits twointerfaces defined by TME 10 ADE (UserInterfaceBaseand Profile)and two that are new (PhoneListIterator andPhoneEntryGUI).

ThePhoneEntryGUI interface defines operations that launch andmanage the application’s GUI. The interface inherits fromTMF_UI::UserInterfaceBase, which defines basic operationscommon to all TME 10 graphical interfaces. ThePhoneListIteratorinterface defines operations that allow a client to use any iterator-basedoperations thatPhoneListProfile contains.

As you can see from the inheritance diagram forPhoneListProfile, notall interfaces are defined to be supported directly; some only exist tobe inherited. For example,PhoneListIterator andPhoneEntryGUIdo not themselves constitute a complete interface. When they areinherited byPhoneListProfile, they become part of a completeinterface.

The interface definitions forPhoneEntryGUI andPhoneListIteratorare shown below.

TMF_CCMS::Profile

PhoneListProfile

PhoneListIterator

PhoneEntryGUI

— Defined by TME 10 ADE

TMF_UI::UserInterfaceBase

Page 47: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Interface Definition

Application Development with TME 10 ADE 2–9

Defining an A

pplicationw

ith IDL

1 // PhoneEntryGUI interface

2 interface PhoneEntryGUI : TMF_UI::UserInterfaceBase,TableMgr::GUI{

3 void ui_phone_props(

4 in TMF_Types::StringList argv,

5 in TMF_Types::StringList env,

6 out TMF_Types::OctetList commands);

7 };

8

9 // PhoneListIterator interface

10 interface PhoneListIterator {

11 boolean next_entries(

12 in long how_many,

13 out PhoneEntryInfoList entry_list)

14 raises(SysAdminException::ExInvalid);

15

16 void destroy_iterator();

17 };

Now we can define thePhoneListProfile interface.PhoneListProfileinherits from the two base interfaces we defined above, plus theinterfaceTMF_CCMS::Profile , which is part of CCMS.18 interface PhoneListProfile : TMF_CCMS::Profile,

19 PhoneEntryGUI,

20 PhoneListIterator

21 {

22 // Operation to create a record in the profile

23 // database.

24 void create_phone_entry(

25 in PhoneEntryInfo new_entry,

26 out string key)

27 raises (SysAdminException::ExExists,

28 SysAdminException::ExPolicy;

29

30 // Operation to create multiple records in the profile

31 //database at once.

32 void create_entries(

33 in PhoneEntryInfoList entries,

34 out TMF_CCMS::Database::add_result_list

35 results);

36

37 // Operation to modify an existing entry.

Page 48: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Interface Definition

2–10 Version 3.6

38 void modify_phone_entry(

39 in string key,

40 in PhoneEntryInfo new_entry)

41 raises (SysAdminException::ExNotFound,

42 SysAdminException::ExPolicy);

43

44 // Operation to remove an entry.

45 void delete_phone_entry(

46 in string key)

47 raises (SysAdminException::ExNotFound,

48 SysAdminException::ExPolicy);

49

50 // Operation to emove several entries at a time.

51 void delete_phone_entries(

52 in TMF_Types::StringList keys)

53 raises (SysAdminException::ExNotFound,

54 SysAdminException::ExPolicy);

55

56 // Get the PhoneEntryInfo for the record

57 // identified by 'key'

58 void get_phone_entry(

59 in string key,

60 out PhoneEntryInfo entry)

61 raises (SysAdminException::ExNotFound);

62

63 // Fetch several records at once.

64 void get_phone_entries(

65 in TMF_Types::StringList keys,

66 out PhoneEntryInfoList entries)

67 raises (SysAdminException::ExNotFound);

68

69 // Return all entries in the database.

70 // Can return an iterator.

71 void get_all_entries(

72 out PhoneEntryInfoList entries,

73 out PhoneListIterator iterator);

74

75 // Return a list of the keys in the profile database

76 void list_phone_entries(

77 out TMF_Types::StringList keys);

78

79 // Given a name, returns every entry

Page 49: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Interface Definition

Application Development with TME 10 ADE 2–11

Defining an A

pplicationw

ith IDL

80 // whose name field matches the string.

81 void find_by_name(

82 in string name,

83 out PhoneEntryInfoList entries,

84 out PhoneListIterator iterator)

85 raises (SysAdminException::ExNotFound);

86 };

plbo Interface

During the design phase (Chapter 2), we identified an interface calledplbo. Theplbo interface supports operations required by objects thatsubscribe to receive updates to the phone list. For a Managed Nodeendpoint (only), the interface also inheritsTMF_SysAdmin::PolicyDrivenBase, which defines many basicoperations and attributes of a TME 10 object. Nearly all objects inTME 10 inherit fromPolicyDrivenBase. For example, thePhoneListProfile interface inheritsPolicyDrivenBase through theTMF_CCMS::Profile interface.

However, for an LCF endpoint, you do not need to inherit fromTMF_SysAdmin::PolicyDrivenBase. LCF endpoints do not need toinherit those basic operations and attributes. In the code listing thatfollows, notice that, for LCF endpoints (#ifdefENDPOINT_BUILD ), the file<tivoli/TMF_SysAdmin.idl> is notincluded.

The interface definition of theplbo interface is shown below.1 #pragma generate False

2 #ifdef ENDPOINT_BUILD

3 #include <mrt/stypes.idl>

4 #include <ccms/CCMS_types.idl>

5 #include “phone.idl”

6 #else

LCF Endpoints Do Not Inherit from PolicyDrivenBaseThis application was originally written to have a ManagedNode objectas the endpoint. It still works with the ManagedNode object as endpoint.However, for LCF, you do not need to inherit fromTMF_SysAdmin::PolicyDrivenBase as you do for a ManagedNode.

Page 50: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Implementation Specification

2–12 Version 3.6

7 #include <tivoli/TMF_SysAdmin.idl>

8 #include <tivoli/CCMS.idl>

9 #include <tivoli/phone.idl>

10 #endif

11 #pragma generate True

12

1 interface plbo : TMF_SysAdmin::PolicyDrivenBase {

2

3 void discover_phonelist(

4 in string filename,

5 out TPL::PhoneEntryInfoList phone_list);

6

7 void update_phone(

8 in any data,

9 in TMF_Types::OctetList dkey,

10 out TMF_Types::OctetList dout);

11 };

Implementation SpecificationIDL defines interfaces and operations, but it does not define how anobject performs those operations. Different objects that support thesame interface often implement the interface’s operations in differentways. For example, consider two objects that inherit acalc_salaryoperation from an interface calledEmployee. The two objects mightimplementcalc_salary differently, depending on whether the objectrepresents an hourly, salaried, or commission employee. The ability toprovide multiple implementations of the same operation is calledoperational(or functional) polymorphism.

TME 10 ADE allows polymorphism of operations by separating thedefinition of an operation from its implementation. In the interfacedefinition, you define interfaces and operations. The implementationspecification goes one step further to define how you will implementthose interfaces and operations as classes and methods.

Class DeclarationWhen you define a class in the implementation specification, you mustspecify the following information:

■ The IDL interface it honors

Page 51: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Implementation Specification

Application Development with TME 10 ADE 2–13

Defining an A

pplicationw

ith IDL

■ The type of class you are defining

■ Optional implementation inheritance

■ Operations for which you will provide method implementations

Since classes implement interfaces, you must associate each class youdefine with an interface. The interface describes the set of operationsthat objects of the class will support.

In addition to specifying the IDL interface the class supports, you mustalso define the class. TME 10 ADE supports four types of classes:

■ Classless Objects — Unique objects that require only a singleinstance. A classless object supports an IDL interface but is notassociated with any particular class.

■ Instantiable Classes — Classes from which you can createinstances. The act of creating an instance of a class is calledobject instantiation.

■ Abstract Classes — Classes whose sole purpose is to act as a baseclass for inheritance. You cannot instantiate instances of anabstract class.

■ Metaclasses — Classes that modify the behavior of another classobject. Unlike other object-oriented programming environments,TME 10 classes are not just compile-time constructs, they arethemselves represented by objects. A class object encapsulatesclass behavior, such as the ability to instantiate objects.Metaclass objects allow you extend the behavior of a classbeyond that provided by default to all TME 10 classes.

Like IDL-defined interfaces, class implementations support the notionof inheritance. Your interface and implementation inheritancehierarchies do not have to be parallel, however. In a sense, interfaceinheritance is an agreement to support a set of pre-defined operations,and implementation inheritance is an agreement to use a pre-definedbehavior for those operations. Since the two inheritance hierarchiesare separate, you can agree to support an inherited set of operationswithout being tied to an inherited set of behaviors (and vice versa).

Page 52: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Implementation Specification

2–14 Version 3.6

Tivoli/Phone Implementation SpecificationFor the Tivoli/Phone application, we define two classes of objects. Thefirst class,PhoneListProfile, implements the operations defined andinherited by thePhoneListProfile interface. The second class,PhoneEndpoint, implements the operations defined by theplbointerface.

PhoneListProfile Class

ThePhoneListProfile class implements thePhoneListProfileinterface. The new class must provide implementations for all theoperations defined by thePhoneListProfile interface and alloperations inherited byPhoneListProfile.

Recalling the interface definition for thePhoneListProfile interface, itdirectly inherits the following interfaces:

■ TPL::PhoneEntryGUI

■ TPL::PhoneListIterator

■ TMF_CCMS::Profile

PhoneListProfile also inherits theTMF_UI::UserInterfaceBaseinterface through thePhoneEntryGUI interface.

The opening statement of an implementation definition is the classdeclaration. The class declaration defines the class type, the interfaceit implements, and any implementations the new class inherits.1 module imp_TPL {

2 //

3 // The implementation PhoneListProfile "honors"

4 // the TPL::PhoneListProfile interface. The

5 // class inherits the implementations of

6 // TMF_CCMS::Profile and TMF_UI::UserInterfaceBase

7 //

8 implementation class PhoneListProfile :

9 imp_TMF_CCMS::Profile,

10 imp_TMF_UI::UserInterfaceBase

11 honors TPL::PhoneListProfile {

12 ...

13 };

Page 53: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Implementation Specification

Application Development with TME 10 ADE 2–15

Defining an A

pplicationw

ith IDL

You can see the class declaration for thePhoneListProfile class in thecode excerpt above. The class honors (supports) thePhoneListProfileinterface.

The class also inherits pre-defined implementations for the operationsdefined by theTMF_CCMS::Profile andTMF_UI::UserInterfaceBase interfaces. Both theProfile and theUserInterfaceBase implementations are good examples of abstractclasses. It would not make sense to instantiate an instance of theUserInterfaceBase class, for example, but it is very valuable whenviewed as a set of inherited behavior.

ThePhoneListProfile class must implement any operations that arenot provided by one of the inherited classes. A class can also chooseto override an implementation that is provided by an inherited class.The body of the class declaration comprises a list of operations forwhich the class will provide method implementations.

The code excerpt below shows the body of thePhoneListProfile classdeclaration. The methods in the declaration have been divided so youcan see which interface defined each operation.14 methods {

15 {

16 // PhoneEntryGUI methods

17 //

18 //These are the GUI methods for which

19 //the application will supply implementations.

20

21 //The one_way_launch method is a method that

22 //is used to hook into the Tivoli-supplied

23 //implementation of the navigate dialog.

24 //Its main purpose is to invoke the

25 //ui_phone_props method.

26

27 one_way_launch,

28 ui_phone_props,

29

30 // PhoneListProfile methods

31 create_phone_entry,

32 create_entries,

33 modify_phone_entry,

34 delete_phone_entry,

Page 54: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Implementation Specification

2–16 Version 3.6

35 delete_phone_entries,

36 get_phone_entry,

37 get_phone_entries,

38 list_phone_entries,

39 find_by_name,

40 get_all_entries,

41

42 //

43 // These are TMF_CCMS::Profile

44 // methods for which the application will

45 // provide implementations.

46 //

47 initializ,

48 populate,

49 validate,

50 enable_validation,

51 disable_validation,

52 _get_validation_enabled,

53 get_default_policies,

54 set_default_policies,

55 get_validation_policies,

56 set_validation_policies,

57 push,

58 remove,

59 copy_records,

60 move_records,

61

62

63 // PhoneListIterator methods

64 //These are the “iterator” methods for which

65 //the application will supply implementations

66

67 next_entries,

68 destroy_iterator,

69

70 } binding = ansi C;

71 };

72 };

73 };

Page 55: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Implementation Specification

Application Development with TME 10 ADE 2–17

Defining an A

pplicationw

ith IDL

ThePhoneListProfile declares two distinct sets of methods in theexcerpt above. The first set includes all the operations defined by thePhoneListProfile, PhoneEntryGUI, andPhoneListIteratorinterfaces. The second group consists of operations inherited fromTMF_CCMS::Profile for which there are no pre-definedimplementations. These operations do not come with an associatedimplementation primarily because their behavior isapplication-specific. For example, thepopulate method must createprofile records from an external source; the exact behavior of theimplementation is obviously specific to each application.

All methods declared by a class must be included in abinding block,which dictates how the TEIDL compiler generates its output files. Thecompiler generates all the method invocation files (client stubs, serverskeletons, method templates) in the chosen binding language. You canhave multiple binding blocks within a class declaration. Currently,TME 10 ADE supports language bindings for ANSI C and Bourneshell. The Tivoli/Phone application uses ANSI C bindings.

PhoneEndpoint Class

ThePhoneEndpointclass implements theplbo interface. The newclass must provide implementations for the operations defined byplbo.1 implementation class imp_plbo :

2 TMF_imp_TSysAdmin::PolicyDrivenBase

3 honors plbo {

4

5 methods {

6 {

7 discover_phonelist,

8 update_phone

9 } binding = ansi C;

10 };

11 };

12

Page 56: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Program Specification

2–18 Version 3.6

ThePhoneEndpoint class honors theplbo interface and inherits theimplementation of thePolicyDrivenBase interface. The class declaresimplementations for two methods:update_phone anddiscover_phonelist. The language binding for the these methods isANSI C.

There is no persistent object associated with an LCF endpoint, so youdo not create instances ofPhoneEndpoint. The objects come intoexistence as needed. For this, we add the class behavior to theEndpoint class, as you saw from the design of the Tivoli/Phoneapplication in Chapter 1, “Anatomy of a TME 10 ADE Application.”

Program SpecificationThe implementation specification defines information about a classimplementation and its methods. However, it does not define theexecution characteristics of the methods. For example, you might wanta method to start, run, and terminate within a single process. Or youmight want several methods to share the same process space. The IDLprogram specification allows you to define the executioncharacteristics of a class’s methods.

Class Names and Friendly Class NamesTME 10 classes have two names: an internal class name and a publicname (also called thefriendly class). The internal class name is theone that appears in the IDL specification. The public version is thename registered with the TME 10 name registry.

The class names used in this book are the friendly class names. Forexample,PhoneEndpoint is the public class name of theimp_plboclass andPhoneListProfile is the public name of theimp_TPL::PhoneListProfile class.

Page 57: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Program Specification

Application Development with TME 10 ADE 2–19

Defining an A

pplicationw

ith IDL

There are three implementation models for a method: programs,commands, and intrinsics. A program method is implemented as aprogram, such as in ANSI C.

Command methods are usually shell scripts. TME 10 assigns a helperprocess to a command method that allows it to read and write standardinput and marshall exceptions.

program

daemonper-method

intrinsiccommand

Implementation Models

Server Types

shared threaded

Execution Styles

LCF Endpoint Methods are Per-MethodMethods for LCF endpoints are always per-method. That is, they aresingle methods that run and terminate.

Page 58: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Program Specification

2–20 Version 3.6

Intrinsic methods are implemented by the ORB. For example, whenyou define an attribute in IDL, the IDL compiler automaticallygenerates methods to get and set the attribute value.

Of the three implementation models for a method, only programmethods require additional information about their executioncharacteristics. The execution characteristics of a command methodare defined by TME 10. An intrinsic method does not requireexecution characteristics since it is implemented by the ORB.

In the program specification, you define theserver programs thatimplement the methods defined by your application’s classes. A serverprogram comprises one or more methods and defines the followingexecution characteristics:

■ Type of server — Controls whether the server handles a singlemethod and terminates, or runs as a long-running daemonprocess that can process multiple method requests serially.

■ Execution style — For a daemon server, defines whether multiplemethods can share the same process at the same time, andwhether all objects of the class share the same process.

■ Start-up commands — Defines any commands that the methodserver must execute each time it starts.

By convention, a program specification file has the extension.prog.The program specification file comprises a set of program definitions,one per server program. The syntax of a program definition is shownbelow.

program name for class { executes { method1, method2, ... } exec_style server_type;

startup { function1, function2, ... };};

Page 59: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Program Specification

Application Development with TME 10 ADE 2–21

Defining an A

pplicationw

ith IDL

Theprogram statement defines a server program and associates itwith a class implementation. You can define as many server programsfor a class as you need.

Theexecutes block enumerates the methods that are serviced by theserver program. After theexecutes block are keywords that control thestyle of execution and type of server that the program uses. There aretwo types of server in TME 10 ADE: per-method servers and daemonservers.

The final part of the program definition is thestartup block. Thisblock specifies any functions that the server must execute beforeinvoking the method implementation.

Per-method ServersPer-method servers are the simplest and most common kind of server.The ORB starts a new server process each time a client invokes amethod. The process exists as long as the method is running andterminates when the method finishes. Although per-method servers arevery straightforward, they do have some drawbacks and limitations:

■ There is overhead associated with starting a server process.If you have a method that is called many times within a shortperiod of time, it might be wasteful to create and kill a processeach time.

■ Multiple invocations of a per-method server do not share thesame process space. If your application runs many per-methodservers at the same time, you can quickly consume large numbersof process slots. There is no programmatic way to limit theamount of machine resources consumed by the concurrentexecutions.

■ The limited duration of the process makes data persistencedifficult. Since the server process terminates when the methodcompletes, you cannot save state information or data betweenmethod invocations without using some form of external storage(such as saving data to an attribute on the object). Storing andfetching persistent data from an external store can incursignificant overhead.

Page 60: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Program Specification

2–22 Version 3.6

■ Methods cannot share data. Since each method invocationreceives its own process, there is no convenient way for methodsto share data. Methods must exchange data through an explicitmechanism such as the Inter-object Message (IOM) service. SeeChapter 5, “Creating Scalable Operations,” for an example ofinter-method communication.

Per-methods servers are a good choice for short-duration, atomicoperations that perform some task and terminate. If you have anoperation that is invoked frequently, must run for long periods, orshare large amounts of data with other methods, you should use adaemon server.

Daemon ServersA daemon server is not directly tied to a single method invocation. TheORB starts a daemon process the first time a client invokes the method.The process does not terminate when the first method completes.Subsequent invocations of the method share the same process as thefirst, either in parallel or in a queued series. Daemon servers providethree advantages over per-method server implementations:

■ They can use less overhead, since the ORB only has to start oneprocess (although a long-running, idle daemon can consumemore resources than a per-method server).

■ They support multiple execution threads, which allow multiplemethods to share the server process simultaneously.

■ They provide an easy way for methods to share memory or passstate information to subsequent method invocations.

If you choose to use a daemon server, you must decide the executionstyle of the daemon. A daemon can be parallel or non-parallel and canbe shared or unshared.

A parallel server allows multiple invocations to run simultaneouslywithin the daemon process. Each time a method is invoked, the ORBcreates a new thread in the process for the method. All threads withina daemon server share the same resources, except the machineregisters (CPU instruction pointer, stack, and so on). This includesglobal memory. In a non-parallel daemon, only one method invocation

Page 61: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Program Specification

Application Development with TME 10 ADE 2–23

Defining an A

pplicationw

ith IDL

can use the daemon at one time. Other invocations wait in a queue fortheir turn to execute.

A daemon server can also be shared or unshared. In a shared daemon,all objects that support the methods implemented by the server canshare a single daemon process. If you choose to define an unshareddaemon server, each object starts its own daemon process.

Although daemon servers are much more powerful and flexible thanper-method servers, they do introduce a set of design problems forwhich you must plan:

■ Non-parallel daemons can introduce queueing delays.Since only one method at a time uses a non-parallel server, otherpending method invocations are forced to wait in a queue. Thiscan cause unacceptable delays if the method is invokedfrequently or takes a long time to complete.

■ Daemon servers can create deadlocks. A deadlock is acondition in which two processes are each waiting for the otherto respond before proceeding. Deadlocks are caused by a methodcalling another method in the same non-parallel daemon(including itself), or by two daemon-based methods invokingeach other.

■ Parallel servers do not have a data barrier between methods.Since multiple threads share the same resources, including globalmemory, one method can corrupt data used by the other methods.Also, if one method terminates fatally and kills the process, allother methods running in that process fail, too.

■ A long-running daemon consumes system resources. You canspecify a time-out so that a daemon process terminates after aperiod of inactivity, releasing the system resources it consumes.

Most of the problems associated with a daemon server can be solvedthrough good programming practices. For example, you can ensuredata integrity and eliminate deadlocks by coordinating use of globalmemory and file descriptors in a parallel server. TME 10 ADEsupports a rich set of locking mechanisms, including mutex locks,friendly mutexes, and semaphores. You can use these lockingmechanisms to control access to critical data by multiple threads.

Page 62: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Program Specification

2–24 Version 3.6

See Chapter 6, “Profile Endpoint Methods,” for examples of lockingwithin a threaded daemon server.

Tivoli/Phone Program SpecificationReturning to the sample Tivoli/Phone application, we must defineprogram specifications for the servers that implement the operations ofthePhoneListProfile andPhoneEndpoint classes.

PhoneListProfile Class

For thePhoneListProfile class, we divide the operations into threeseparate implementation servers:

■ One for the “atomic” methods

■ One for operations that can return or respond to an iterator

■ One for the user interface operations

The first server implements all the atomic operations that thePhoneListProfile class supports. This includes all the operations tocreate, retrieve, remove, and change records in the profile database.This server also supports the operations inherited from theTMF_CCMS::Profile interface that we must implement.

Since the operations implemented by this server are atomic in nature(they do not interact directly with each other), we can implement themas a per-method server program. The code server definition from theprogram specification is shown below.1 program Phone_prog1 for imp_TPL::PhoneListProfile {

2 executes {

3 create_phone_entry,

4 create_entries,

5 modify_phone_entry,

6 delete_phone_entry,

7 delete_phone_entries,

8 get_phone_entry,

9 get_phone_entries,

10 initializ,

11 populate,

12 validate,

13 enable_validation,

14 disable_validation,

Page 63: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Program Specification

Application Development with TME 10 ADE 2–25

Defining an A

pplicationw

ith IDL

15 _get_validation_enabled,

16 get_default_policies,

17 set_default_policies,

18 get_validation_policies,

19 set_validation_policies,

20 push,

21 remove,

22 move_records,

23 copy_records

24 } per method;

25

26 startup {

27 "tas_init"

28 };

29 };

Theprogram statement (line 1) defines a server calledPhone_prog1,which supports theimp_TPL::PhoneListProfile class. The methodssupported by the server are included in theexecutes block. Thestartup block lists any functions that TME 10 is to run when it startsa new server process. For this server, we need only to execute thetas_init function, which initializes the Tivoli Application Serviceslibrary.

The second server defined for thePhoneListProfile class contains allthe operations that can return or receive an iterator handle. Thisincludes theget_all_entries andfind_by_name operations from thePhoneListProfile interface, and thenext_entries anddestroy_iterator operations from thePhoneListIterator interface.

What type of server do iterator-based operations require? Since somestate information must persist between the initial method call andsubsequent calls to the iterator operations, we can use a daemon server.We will make the daemon threaded (parallel) so that a single serverprocess can handle several iterator requests simultaneously. Thedaemon server is not shared, however, so each object will have its ownserver process for handling iterator requests. The code excerpt belowshows the program specification for the daemon server.1 program Phone_prog2 timeout = 180 for

2 imp_TPL::PhoneListProfile {

3 executes {

4 list_phone_entries,

Page 64: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Program Specification

2–26 Version 3.6

5 get_all_entries,

6 find_by_name,

7 next_entries,

8 destroy_iterator

9 } threaded daemon;

10

11 startup {

12 "tas_init",

13 "query_init"

14 };

15 };

The excerpt defines a threaded daemon server,Phone_prog2, for theimp_TPL::PhoneListProfile class. To prevent the daemon serverfrom running for long periods between invocations, we will give it atime-out of 180 seconds.

Thestartup block defines two functions that TME 10 executes whenit starts the daemon server process. Thetas_init function initializes theTivoli Application Services library. Thequery_init function — whichwe must write—initializes the data structures required by our iteratorimplementation.

See Chapter 5, “Creating Scalable Operations,” for an in-depth look atthe implementation of Tivoli/Phone’s iterator-based operations.

The final server program that we must define for thePhoneListProfileclass is one to support the operations that launch and manage theclass’s user interface. For this server, we will use a threaded server somultiple users can run the user interface on the same object.

The code excerpt below shows the program specification for the userinterface operations’ daemon server.1 program Phone_ui_prog1 timeout = 180 for

2 imp_TPL::PhoneListProfile {

3 executes {

4 ui_phone_props

5 one_way_launch,

6 } threaded daemon;

7

Page 65: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Program Specification

Application Development with TME 10 ADE 2–27

Defining an A

pplicationw

ith IDL

8 startup {

9 "phone_gui_init"

10 };

11 };

The program specification defines a threaded daemon server calledPhone_ui_prog1, which implements theui_phone_props operationand aone_way_launch operation. Thestartup block defines anoperation calledphone_gui_init that TME 10 will execute each timeit starts a server process. Thephone_gui_init function is implementedby the Tivoli/Phone application.

Chapter 7, “Creating an Application User Interface,” covers theimplementation of the operations supported by thePhone_ui_prog1server.

PhoneEndpoint Class

The server requirements of thePhoneEndpoint class are muchsimpler than those ofPhoneListProfile, since the former onlysupports two operations:discover_phonelistandupdate_phone.Both operations fit the requirements for a per-method server(short-duration, atomic in nature), so we can define a singleper-method server program for them.1 program plbo_prog1 for imp_plbo {

2 executes {

3 discover_phonelist,

4 update_phone

5 } per method;

6 startup {

7 "tas_init"

8 };

9 };

The code excerpt above defines a per-method server program calledplbo_prog1 for thePhoneEndpoint class. TME 10 will execute thetas_init function whenever it starts a server process.

Page 66: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Installation Specification

2–28 Version 3.6

Installation SpecificationThe final step in creating an application definition is to define how theclass implementations behave when they are installed in TME 10. Thebody of a class installation specification can contain any of thefollowing:

■ Access control lists for each method

■ Definitions of new access roles

■ Execution privileges for each method

■ The path names of the method binaries

■ A set of commands to be executed when the class is installed inTME 10

The installation specification for thePhoneListProfile andPhoneEndpoint classes are fairly straightforward examples. Neitherclass defines methods that require special privileges or role promotion,so the installation specification contains:

■ Access control lists for the class’s methods

■ Path names of the method binaries

■ Commands to execute at installation time

PhoneListProfile Installation SpecificationThe installation definition defines the class it represents and the serverprograms it comprises in the installation specification. In the case ofPhoneListProfile, the server programs are the three defined inTivoli/Phone’s program specification.1 module ist_TPL {

2 installation PhoneListProfile for

3 imp_TPL::PhoneListProfile

4 with prog_TPL::Phone_prog1,

5 prog_TPL::Phone_ui_prog1,

6 prog_TPL::Phone_prog2

7 {

8 ...

9 }

Page 67: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Installation Specification

Application Development with TME 10 ADE 2–29

Defining an A

pplicationw

ith IDL

The first thing we encounter in thePhoneListProfile installationspecification is theacl block.

Since we created an authorization map during the design phase of theapplication (see Chapter 2), theacl block simply codifies the map.

10 // Define the ACLs required for the

11 // application's methods.

12 acl {

13

14 // Require at least the SENIOR role.

15 {

16 imp_TPL::PhoneListProfile::initializ,

17 imp_TPL::PhoneListProfile::get_default_policies,

18 imp_TPL::PhoneListProfile::set_default_policies,

19 imp_TPL::PhoneListProfile::get_validation_policies,

20 imp_TPL::PhoneListProfile::set_validation_policies

21 } = { SENIOR_ACL };

22

Operation Required RolesSpecial

Privileges

create_phone_entry admin No

create_entries admin No

modify_phone_entry admin No

modify_phone_entries admin No

delete_phone_entry admin No

delete_phone_entries admin No

get_phone_entry admin or user No

get_phone_entries admin or user No

get_all_entries admin or user No

list_all_entries admin or user No

find_by_name admin or user No

Page 68: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Installation Specification

2–30 Version 3.6

23 // Require at least the ADMIN role.

24 {

25 imp_TPL::PhoneListProfile::create_phone_entry,

26 imp_TPL::PhoneListProfile::create_entries,

27 imp_TPL::PhoneListProfile::modify_phone_entry,

28 imp_TPL::PhoneListProfile::delete_phone_entry,

29 imp_TPL::PhoneListProfile::delete_phone_entries,

30 imp_TPL::PhoneListProfile::populate,

31 imp_TPL::PhoneListProfile::validate,

32 imp_TPL::PhoneListProfile::enable_validation,

33 imp_TPL::PhoneListProfile::disable_validation,

34 imp_TPL::PhoneListProfile::push,

35 imp_TPL::PhoneListProfile::remove,

36 imp_TPL::PhoneListProfile::move_records,

37 imp_TPL::PhoneListProfile::get_all_entries,

38 imp_TPL::PhoneListProfile::ui_phone_props,

39 imp_TPL::PhoneListProfile::one_way_launch

40 imp_TPL::PhoneListProfile::copy_records

41 } = { ADMIN_ACL };

42

43 // Require at least the USER role.

44 {

45 imp_TPL::PhoneListProfile::get_phone_entry,

46 imp_TPL::PhoneListProfile::get_phone_entries,

47 imp_TPL::PhoneListProfile::list_phone_entries,

48 imp_TPL::PhoneListProfile::find_by_name,

49 imp_TPL::PhoneListProfile::next_entries,

50 imp_TPL::PhoneListProfile::

51 _get_validation_enabled,

52 imp_TPL::PhoneListProfile::destroy_iterator

53 } = { USER_ACL };

54 };

Although TME 10 does not enforce its pre-defined roles as a hierarchy,it provides convenience macros to help you use them that way if yourapplication requires it. Tivoli/Phone uses these convenience macros,which end in_ACL , in itsacl block. TheSENIOR_ACL macro, forexample, expands into the strings “senior,” “admin,” and “user.”

The second element of this installation specification is thepath block.When a client requests a method from an object, the TME 10 ORBmust locate and invoke the method implementation. Thepath block

Page 69: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Installation Specification

Application Development with TME 10 ADE 2–31

Defining an A

pplicationw

ith IDL

allows you to specify the location of the server programs that containthe class method implementations. The path is always relative to thebin directory under the TME 10 installation directory. The TME 10bin directory is divided so there is a sub-directory for eacharchitecture. You must specify an installation path for eacharchitecture type that your application supports.

ThePhoneListProfile class implements its methods as three separatebinaries:phone_core, phone_query, andphone_ui.55 external path {

56

57 // Location of the core-method method

58 // program.

59 {

60 imp_TPL::PhoneListProfile::create_phone_entry,

61 imp_TPL::PhoneListProfile::create_entries,

62 imp_TPL::PhoneListProfile::modify_phone_entry,

63 imp_TPL::PhoneListProfile::delete_phone_entry,

64 imp_TPL::PhoneListProfile::delete_phone_entries,

65 imp_TPL::PhoneListProfile::get_phone_entry,

66 imp_TPL::PhoneListProfile::get_phone_entries,

67

68 imp_TPL::PhoneListProfile::initializ,

69 imp_TPL::PhoneListProfile::populate,

70 imp_TPL::PhoneListProfile::validate,

71 imp_TPL::PhoneListProfile::enable_validation,

72 imp_TPL::PhoneListProfile::disable_validation,

73 imp_TPL::PhoneListProfile::

74 _get_validation_enabled,

75 imp_TPL::PhoneListProfile::get_default_policies,

76 imp_TPL::PhoneListProfile::set_default_policies,

77 imp_TPL::PhoneListProfile::

78 get_validation_policies,

79 set_validation_policies,

80 imp_TPL::PhoneListProfile::push,

81 imp_TPL::PhoneListProfile::remove,

82 imp_TPL::PhoneListProfile::move_records,

83 imp_TPL::PhoneListProfile::copy_records

84 } = { "default", "/TME/PHONE/phone_core"; };

85

86 // Iterator-based method program.

Page 70: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Installation Specification

2–32 Version 3.6

87 {

88 imp_TPL::PhoneListProfile::list_phone_entries,

89 imp_TPL::PhoneListProfile::get_all_entries,

90 imp_TPL::PhoneListProfile::find_by_name,

91 imp_TPL::PhoneListProfile::next_entries,

92 imp_TPL::PhoneListProfile::destroy_iterator

93 } = { "default", "/TME/PHONE/phone_query"; };

94

95 // Location for UI program

96 {

97 imp_TPL::PhoneListProfile::ui_phone_props,

98 imp_TPL::PhoneListProfile::one_way_launch

99 } = { "default", "/TME/PHONE/phone_ui"; };

100 };

In this case, the method binaries map one to one with the serverprograms defined in the program specification, but it is not arequirement. You can place methods that have different executionstyles in the same method binary. So, a method that executes as aper-method server can be in the same method binary as a method thatruns as a daemon server.

All three method binaries are stored in theTME/PHONEsub-directory under the TME 10bin directory. Although you mustspecify an installation path for every architecture type, you can use thedefault keyword to simplify things.

Thedefault keyword indicates that the method binaries are stored inthe same relative location for all platforms. So, in the Tivoli/Phoneapplication, the SunOS 4.x binaries are stored in/tme_install/bin/sunos4/TME/PHONE and the HP-UX 9.x binariesin /tme_install/bin/hpux9/TME/PHONE . If you do not use thedefault keyword, you must enumerate each architecture type and therelative path to its binaries separately.

The final part of an installation specification is the list of commandsthat TME 10 executes when it installs the class. In the case of thePhoneListProfile class, we specify the name of a script,phone.init,that is automatically executed when the class is installed. Since theinitialization commands are stored in a script instead of being listeddirectly in the installation specification, you can change the commandswithout recompiling the IDL.

Page 71: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Installation Specification

Application Development with TME 10 ADE 2–33

Defining an A

pplicationw

ith IDL

101 // Define the actions taken when the class

102 // is installed in the TME. We run the

103 // phone.init script in this case.

104 initialize {

105 "$METHODPATH/phone.init

106 $imp_TPL_PhoneListProfile_CO $METHODPATH";

107 };

108 };

109 };

The commands in theinitialize block have access to two environmentvariables. Theclass_CO variable contains the object reference of theclass object. The class part of the variable is the fully qualified classname (TPL_PhoneListProfile_CO). TheMETHODPATH variablecontains the path to the directory where the class configuration files(generated by the TEIDL compiler) are located.

What kinds of commands get executed at installation time? ThePhoneListProfile class performs a variety of chores at installation,such as creating notice groups, registering with the Tivoli NameRegistry, and configuring the class presentation object. The contents ofthephone.init script are shown below.1 #!/bin/sh -x

2

3 imp_phone_CO=$1

4 METHODPATH=$2

5 FriendlyClass="PhoneListProfile"

6

7 # Register the class with the name registry.

8 set +e

9 wlookup -r Classes $FriendlyClass

10 if [ $? -ne 0 ]; then

11 set_friendly_name $imp_phone_CO $FriendlyClass

12 fi

13 set -e

14

15 #

16 # Set up the class as an indirectly managed resource.

17 # All profile classes are considered to be “indirectly”

18 # managed, since they exist only within the context of a

19 # profile manager.

20 #

Page 72: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Installation Specification

2–34 Version 3.6

21 idlcall $imp_phone_CO TMF_SysAdmin::InstanceManager::

22 indirectly_managed TRUE

23

24

25 # Set up the class presentation object

26 initpres $imp_phone_CO -class -create \

27 dialog phone_props $METHODPATH/phone_props.d \

28 dialog add_dialog $METHODPATH/add_dialog.d \

29 dialog edit_dialog $METHODPATH/edit_dialog.d \

30 bitmap phone_icon xpm $METHODPATH/phone_icon.xpm \

31 bitmap locked xpm $METHODPATH/locked.xpm \

32 bitmap fixed xpm $METHODPATH/fixed.xpm \

33 state normal $METHODPATH/phone_icon.d xpm \

34 $METHODPATH/phone_icon.xpm \

35 parent TableMgrGuiDlgs

36

37 ...

38

39 # Create the application's notice group

40 NTFGM=`wlookup -r Classes TMF_Notice`

41 wlookup -r TMF_Notice "Address Book"

42 if [ $? -ne 0 ]; then

43 notice_group=`idlcall -T top $NTFGM \

44 TMF_Notice::NoticeManager::create_notice_group \

45 '"Address Book" 168'`

46 fi

47 ...

PhoneEndpoint Class Installation SpecificationThePhoneEndpoint class implements two operations:update_phone anddiscover_phonelist. Theupdate_phone methodrequires theadmin or user role, whilediscover_phonelist onlyrequires theuser role.1 installation ist_PhoneEndpoint for imp_plbo

2 with plbo_prog1 {

3 acl {

4 {

5 update_phone

6 } = { ADMIN_ACL };

7

8 {

Page 73: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Installation Specification

Application Development with TME 10 ADE 2–35

Defining an A

pplicationw

ith IDL

9 discover_phonelist

10 } = { USER_ACL };

11 };

We house the implementations for the two methods in a single methodbinary. The method binary will reside in the same directory(TME/PHONE ) as thePhoneListProfile class’s method binaries.12 external path {

13 {

14 update_phone,

15 discover_phonelist

16 } = { "default", "/TME/PHONE/plbo_prog1"; };

17 };

Finally, the installation specification includes a script,plbo.init , whichis run when the class is installed in TME.18 initialize {

19 "$METHODPATH/plbo.init

20 $imp_Endpoint_CO $METHODPATH";

21 };

22 };

Theplbo.init script registers the friendly class name with the nameregistry and adds the class behavior to theManagedNodeclass.1 #!/bin/sh -x

2

3 imp_plbo_CO=$1

4 METHODPATH=$2

5

6 # Register the friendly name with the name registry

7 FriendlyClass="PhoneEndpoint"

8 wlookup -r Classes $FriendlyClass

9 if [ $? -ne 0 ]; then

10 set_friendly_name $imp_plbo_CO $FriendlyClass

11 fi

12

13 BEHAVIOR=`objcall $imp_plbo_CO _get_behavior`

14 CLO=`wlookup Library`

15

16 # Add the class behavior to ManagedNode

17 set +e

18 ep_class_name="ManagedNode"

19 EP_CLASS=`objcall $CLO _lookup_object $ep_class_name`

Page 74: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Installation Specification

2–36 Version 3.6

20 status=$?

21 if [ $status -eq 0 ]; then

22 winstendpt $imp_plbo_CO

23 fi

24 set -e

Finally, the scriptsample_app.init adds the endpoint behavior to theEndpoint class (for LCF endpoints).

1 #!/bin/sh

2 set -x*

3

4 set -e

5 #

6 # Put endpoint methods in inheritance list of Endpoint

7 # class

8 #

9 CLO=`wlookup Library`

10

11 if [ -z “$imp_plbo_CO” ] ; then

12 imp_plbo_CO=`objcall $CLO _lookup_objectPhoneEndpoint`

13 fi

14

15 if [ -n “$imp_plbo_CO” ] ; then

16 imp_plbo_BO=`objcall $imp_plbo_CO _get_behavior`

17 fi

18 set +e

19

20 ep_class_name=”Endpoint”

21 EP_CLASS=`objcall $CLO _lookup_object $ep_class_name`

sample_app.initsample_app.init does the following:

■ Installs endpoint behavior on the Endpoint class (plbo.init installs iton theManagedNode class)

■ Forces the gateway to update its method header cache with the newinformation

■ Sets up dependencies, including specifying the CCMS shared libraryas a dependency

Page 75: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Installation Specification

Application Development with TME 10 ADE 2–37

Defining an A

pplicationw

ith IDL

22 status=$?

23 if [ $status -eq 0 ]; then

24 # check and see if behavior is already in inheritance

25 # list of Endpoint

26 EP_BO=`objcall $EP_CLASS _get_behavior`

27 objcall $EP_BO oi_get_list | grep $imp_plbo_BO>/dev/null 2>&1

28 status=$?

29

30 # if behavior not in inheritance list, add it

31 if [ $status -ne 0 ] ; then

32 winstendpt $imp_plbo_CO $EP_CLASS

33

34 # now force gateway(s) to update method

35 # header cache(s)

36 for gwoid in `wlookup -o -r Gateway -a`

37 do

38 idlcall $gwoid gateway_dbcheck

39 done

40 fi

41 fi

42

43 set -e

44

45 #

46 # Set up dependencies

47 #

48

49 if wlookup -r DependencyMgr sample_app-lcf-base ; then

50 :

51 else

52 # Specify base LCF shared library dependencies.

53 wdepset -c sample_app-lcf-base \

54 -a lib libmrt \

55 -a lib libcpl \

56 -a lib libdes

57 fi

58

59 wchdep @Classes:PhoneEndpoint@DependencyMgr:sample_app-lcf-base update_phone

60 wchdep @Classes:PhoneEndpoint@DependencyMgr:sample_app-lcf-base discover_phonelist

61

Page 76: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Installation Specification

2–38 Version 3.6

62

63 if wlookup -r DependencyMgr sample_app-libccms_lcf ;then

64 :

65 else

66 # Specify the CCMS shared library dependency.

67 wdepset -c sample_app-libccms_lcf \

68 -a lib libccms_lcf

69 fi

70

71 wchdep @Classes:PhoneEndpoint@DependencyMgr:sample_app-libccms_lcf update_phone

72 wchdep @Classes:PhoneEndpoint@DependencyMgr:sample_app-libccms_lcfdiscover_phonelist

73

Additional IDL Files for LCF EndpointsBecause the Tivoli/Phone application was originally written for ManagedNodes as endpoints and then ported to use LCF endpoints, you will findsome additional IDL files in the source that you would not otherwise find.These additional files provide an exception definition needed for LCF butnot part oflibmrt . It is included inendpoint/src/plbo_lcf.idl:

1 #pragma generate False

2 #include <mrt/stypes.idl>

3 #pragma generate True

4

5 exception ExFailed : SysAdminException::ExException {

6 string operation_name;

7 };Exceptions are always declared in the.idl file; in this particular case, theexceptionExFailed is not included inlibmrt , so this private version wascreated for the endpoint to use. The other three files (plbo_lcf.imp,plbo_lcf.ist, plbo_lcf.prog) were created and included to constitute acomplete IDL environment.

Page 77: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Compiling an IDL Specification

Application Development with TME 10 ADE 2–39

Defining an A

pplicationw

ith IDL

Compiling an IDL SpecificationTME 10 ADE provides a compiler to generate code from a TivoliExtended IDL description of an application. The command, calledtidlc , produces source code to manage much of the interactionbetween clients that request methods and the application’s methodimplementations. The compiler generates numerous files, but they fallinto the following general categories:

■ Client stub source

■ Server skeleton source

■ Defines

■ Main program source

■ Installation scripts and data

■ Method templates

While you usetidlc to compile on the server side, on the endpoint side,you useltid to compile.

The client stub is the mechanism that a client uses to invoke a method.The client stub marshals data being passed to and from the client. Ifyou use the ANSI C language binding, the client stub looks like afunction call. In the code below, the client requests theget_all_entriesmethod.

t_TPL_PhoneListProfile_get_all_entries(obj, &ev, Trans_sub, cache, &iterator);

Compiling Endpoint Code with ltidltid is the special front-end script to run the TEIDL compiler you use tocompile on the endpoint side.ltid is a wrapper aroundtidlc . It has nocommand line arguments of its own; it passes whatever arguments yougive it totidlc without modification.ltid runstidlc and then modifiesthe standard TEIDL compiler-generated code to enable it to run on anendpoint.

Page 78: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Compiling an IDL Specification

2–40 Version 3.6

The compiler constructs the function name from the name of theoperation, the interface, and the module that contains the interface.TME-style stubs (stubs that support transactions and exceptions), havea t_ prefix. In the above example, the methodget_all_entries is partof thePhoneListProfile interface, which is defined in theTPLmodule.

The duties of a server skeleton are similar to those of the client stub,except that it marshals data passing to and from a serverimplementation.

The code for the stubs and skeletons is self-contained; you do not haveto modify it. Simply compile the code generated by the TME 10 ADEIDL compiler and link it into your method binary. The compilergenerates both stubs and skeletons in both CORBA-compliant andTME 10 form. The TME 10 version is actually a wrapper for theCORBA-compliant form, so you will need to compile both versions.

The IDL compiler also generates header files that contain prototypesfor every compiler-generated function and type information for alldata types defined in the interface definition. Like the stub andskeleton source code, you simply need to include the generated headerfiles, you do not need to modify them.

IDL Compiler TrickOne of the drawbacks of having the IDL descriptions divided into fourfiles is that it is possible for one or more of the compiled versions to getout of step with the other files. You can solve this problem by using the#include directive to tie the four files together. When the TEIDLcompiler encounters an#include directive, it compiles the specifiedfile.

The Tivoli/Phone installation specification includes the programspecification, which in turn includes the implementation specification.The implementation includes the interface definition to complete thechain.

Tying the files together ensures that whenever the installationspecification is recompiled, the entire IDL description is alsorecompiled.

Page 79: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Compiling an IDL Specification

Application Development with TME 10 ADE 2–41

Defining an A

pplicationw

ith IDL

The IDL compiler generates amain function for every method binaryyou define for your application. Themain functions are the entry pointfor an implementation program and handle routing the client’s requestto the proper method implementation. Compile and link the mainprogram files into your method binaries.

The installation scripts and data generated by the compiler help youinstall your class in TME 10. The compiler produces a configurationscript that adds the class information to the TME 10 interfacerepository. The compiler also generates tar files that contain the classconfiguration information in the format required by the interfacerepository.

The IDL compiler produces two empty method templates for everymethod in a class: a CORBA template and a TME 10 template. TheTME 10 template is a superset of the CORBA template that supportsTME 10-style transactions and exceptions. You should fill in only oneversion of the template to implement the method; you can ignore theother.

If you use the ANSI C language binding, the method template is afunction header with an empty body. The name of the method templateis composed of the operation and class name, and module. The TME10-style template also has at_ prefix.

CORBA-Style Method Template

imp_TPL_PhoneListProfile_get_all_entries(obj, &ev, Trans_sub, args, ...);

TME-Style Method Template

t_imp_TPL_PhoneListProfile_get_all_entries(obj, &ev, Trans_sub, args, ...);

Page 80: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Compiling an IDL Specification

2–42 Version 3.6

This section is intended as a quick introduction to the types of codethat the IDL compiler produces for you. For a more thoroughdiscussion of the output generated by the Tivoli Extended IDLcompiler, see theFramework Services Manual.

Replacing Method TemplatesThe TEIDL compiler writes the CORBA-style method templates for aprogram in a file calledserver_meth.c, whereserver is the name ofthe server program that implements the methods. The TME-styletemplates go int_server_meth.c.

Since you will fill in the method templates with code, the TEIDLcompiler does not overwrite the template files if you recompile. Thecompiler writes the new templates to files calledserver_meth.c.tidlcandt_server_meth.c.tidlc. If you change an interface definition thatresults in a change to a method header, you must merge it with theexisting implementation by hand.

Page 81: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Development with TME 10 ADE 3–1

Method Im

plementations

3Method Implementations

“OK, what now?”

This is usually the first question developers ask when they havefinished creating and compiling their IDL definition. The answer is, ofcourse, “it depends.”

If you think of your application in terms of clients and servers, yourmethod implementations are servers and your user interface (graphicaland command-line) are clients. One simple strategy is to implementand test your servers (methods) before moving on to your clients (userinterface). If you have a stable base of methods, you will have a mucheasier time implementing your user interface.

On the other hand, implementing the user interface first gives you aconvenient platform from which to test your methods as youimplement them. Implementing the user interface first can provide anearly prototype you can use to test the usability of the application.

The strategy chosen for the Tivoli/Phone application was to create themethod implementations first. The first methods implemented were theinitializ method (required for all profile-based applications) and themethods to create and retrieve profile records. Small client programswere written to test these methods. After these basic methods, theremaining methods were developed and tested in parallel.

When the methods were finished, work began on the graphical userinterface. The application’s graphical interface acts as an client to theobject and its methods. The command-line interface was essentially

3

Page 82: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The initializ Method

3–2 Version 3.6

complete when the GUI work began, since the CLI commands were aby-product of the method testing.

The initializ MethodWhen a user creates a new instance of a profile, CCMS calls theinitializ operation on the new profile. This operation creates the profiledatabase and initializes the attributes of the new profile object.

Your application inheritsinitializ as part of theTMF_CCMS::Profileinterface. There is no system implementation for the method, however,so you must provide your own. The IDL signature of theinitializmethod is shown below.

void initializ(in string label, in context_type a_context, in ProfileOrganizer profile_org, in Profile source_obj);

The first task for theinitializ method is to create a profile database. Todo this, theinitializ method runs the methodTMF_CCMS::ProfileOrganizer::create_db on the profile manageror endpoint that contains the new profile.1 void t_imp_TPL_PhoneListProfile_initializ(

2 TPL_PhoneListProfile _TPL_PhoneListProfile,

3 Environment *_ev,

4 transaction _transaction,

5 char *label,

6 TMF_CCMS_ProfileBase_context_type a_context,

7 TMF_CCMS_ProfileOrganizer profile_organizer,

8 TMF_CCMS_Profile source_obj) {

Parameter Description

label Label of the new profile object

a_context Context where the new profile object resides; eitherprofile_manager or profile_endpoint

profile_org Object reference of the profile manager or endpoint

source_obj Object reference of an existing profile to clone

Page 83: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The initializ Method

Application Development with TME 10 ADE 3–3

Method Im

plementations

9

10 ml_t *mh = ml_create();

11 Environment env = {0};

12 char *pdr_record_key, *pvr_record_key;

13 char *db_name = PHONELIST_DBNAME;

14 SysAdminTypes_ObjectLabel pvr_obj_label,

15 pdr_obj_label;

16 TMF_CCMS_Profile_push_params push_params;

17

18 if (label == NULL || *label == ‘\0’) {

19 ExPhoneError *ex = (ExPhoneError *)ExPhoneErrorNew(

20 phone_msgs,

21 no_label);

22 Throw(ex->type_name, ex);

23 }

24

25 TMF_CCMS_Database_record pdr, pvr;

26

27 Try {

28 t_TMF_CCMS_ProfileOrganizer_create_db(

29 profile_organizer, &env,

30 Trans_revocable, db_name,

31 ENDPOINT_METHOD, TRUE);

32 }

33 /*

34 * Ignore an ExExists exception, since all it

35 * means is that somebody else created it first.

36 */

37 Catch(ExExists, ex) {

38 /* Do Nothing */

39 }

40 Catch(ExFileWDenied, ex) {

41 ExPhoneError1 *ex1 = (ExPhoneError1 *)

42 ExPhoneError1New(phone_msgs,

43 create_db_failed,

44 db_name);

45 ContextThrow(ex1->type_name, ex1);

46 }

47 EndTry;

Page 84: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The initializ Method

3–4 Version 3.6

Line 28 is the invocation of thecreate_db method stub. In addition tocreating the database,create_db also registers the name of the methodthat is called on each endpoint when your profile is distributed.

Thecreate_db method can throw two exceptions:ExExists andExFileWDenied. An ExExists exception means that the databasealready exists. This is not an error in this case, since it is possible thatanother profile of the same type already created the database. The newprofile can just use a partition of the existing database. AnExFileWDenied exception, however, indicates a more seriousproblem, one the method is not equipped to handle. In this case (lines28-31), the method usesContextThrow to wrap the exception insidean exception of its own.

The next task forinitializ is to create default and validation policyrecords for the new profile. The policy records store the user-definedpolicies that are enforced on the records in the profile database. Thepolicy records should have unique keys that cannot clash with the keysof regular profile records. In the Tivoli/Phone application, forexample, the policy record keys are the object reference of the profileplus a special prefix.

When theinitializ method creates the policy records, it also suppliesthe records’ attributes with an initial set of policies. The source of theinitial policies is determined by how the new profile is being created.If the new profile is being “cloned” from an existing profile,initializ

Using ContextThrowWhen a system function or method called by your application throws anexception, it is a good idea to add an application-specific context to theerror. You can useContextThrow to add more information to anexception or just wrap it in a more user-friendly message.

For example, suppose your application catches an exception whilewriting to a file. You can make the error message slightly morepalatable to a user withContextThrow:

Could not add new user Fred to the /etc/passwd file. There was aproblem writing to the file. The error was:

Error writing file: No write permission

Page 85: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The initializ Method

Application Development with TME 10 ADE 3–5

Method Im

plementations

also clones the default and validation records. If the new profile isbeing created from scratch,initializ seeds the records with hard-codedvalues.48 /*

49 * If the new profile is being cloned, get the

50 * default and validation policies from the

51 * source object

52 */

53 if (t_Object_is_nil(source_obj, &bogus_env) &&

54 strcmp(label, DEF_PHONE_PROFILE_NAME) != 0) {

55

56 source_obj = find_default_profile();

57 ml_attach_Object_reference(mh, source_obj);

58

59 } if (t_Object_is_nil(source_obj, &bogus_env)) {

60 ExPhoneError *ex =

61 (ExPhoneError*)ExPhoneErrorNew(

62 phone_msgs,

63 no_template_instance);

64 Throw(ex->type_name, ex);

65 }

66 }

67

68 /*

69 * Initialize default and validation records.

70 */

71 seq_init((sequence_t *)&pdr.attrs);

72 seq_init((sequence_t *)&pvr.attrs);

73

74 /*

75 * If we are not initializing the default profile,

76 * get the default and validation records from the

77 * default profile. If we are initializing the default

78 * profile, we skip this.

79 /*

80 if (strcmp(label, DEF_PHONE_PROFILE_NAME) != 0) {

81

82 /* Get the attributes of the default and validation

83 * records from the source object or default profile.

84 */

Page 86: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The initializ Method

3–6 Version 3.6

85t_TPL_PhoneListProfile_get_validation_policies

(source_obj,

86 &bogus_env,

87 Trans_sub,

88 &pvr.attrs);

89 ml_attach_ORB_output(mh, &pvr.attrs);

90

91 t_TPL_PhoneListProfile_get_default_policies(source_obj,

92 &bogus_env,

93 Trans_sub,

94 &pdr.attrs);

95 ml_attach_ORB_output(mh, &pdr.attrs);

96

97 /* If this is the “bootstrap” profile, set the policies

98 * to default, hard-coded initial values.

99 */

100

101 else {

102 init_default_def_rec(_TPL_PhoneListProfile,

103 &pdr.attrs);

104 init_default_val_rec(_TPL_PhoneListProfile,

105 &pvr.attrs);

106 }

107 }

In the code fragment above, the method checks to see if the new profileis being cloned (source_obj is notOBJECT_NIL ). If so,initializ runstheget_validation_policies andget_default_policies methods on thesource object to obtain its policy records (lines 81 and 87).

If the new profile is not being cloned, the method calls its ownfunctions to provide hard-coded initial values for the policy records.

Next, the method adds the default policy record to the new profile.First, it creates keys for both the default and validation records. Then,the method sets the fields of the record and runs theTMF_CCMS::Database::add_record method on the profileorganizer to add the policy records to the profile database.108 /*

109 * Create keys for the default and validation records.

110 * The key is the OID of the profile object plus a prefix

Page 87: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The initializ Method

Application Development with TME 10 ADE 3–7

Method Im

plementations

111 * that identifies the record type.

112 */

113 pdr_record_key =

114 make_def_rec_key(_TPL_PhoneListProfile);

115 ml_attach_addr(mh, pdr_record_key);

116 pvr_record_key =

117 make_val_rec_key(_TPL_PhoneListProfile);

118 ml_attach_addr(mh, pvr_record_key);

119

120 /*

121 * Set the values of the default record

122 */

123 pdr.pm_classname = pdr.pe_classname =

124 PHONE_PROFILE_CLASS;

125 pdr.flags = TMF_CCMS_Database_display;

126 pdr.parent = pdr.validation = OBJECT_NIL;

127 pdr.partition = pdr_record_key;

128 pdr_obj_label.label = label;

129 pdr_obj_label.objref = _TPL_PhoneListProfile;

130

131 /* Add the default record to the new profile */

132 t_TMF_CCMS_Database_add_record(

133 profile_organizer, &bogus_env,

134 Trans_sub, db_name, pdr_record_key,

135 &pdr, &pdr_obj_label);

136

TheTMF_CCMS::Profile interface defines an attribute calledrecord_key that contains the key of a record in the database. CCMSconsults the fields of this record when it needs information about theprofile. For example, CCMS examines thepm_classname andpe_classname fields on the record to determine what class of object tocreate on a subscriber. CCMS also examines the record’sdisplay flagto determine if the object can appear as an icon on the TME 10desktop.

In the Tivoli/Phone application, the default policy record is the recorddirectly associated with the profile object, since every phone profilemust have one. Theinitializ method sets thepm_classname andpe_classname fields of the default record to the name of the phoneprofile class. The method also sets the record’sdisplay flag, since thephone profile can appear on the TME 10 desktop.

Page 88: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The initializ Method

3–8 Version 3.6

After initializ creates the default policy record, it creates a validationpolicy record. The code looks very similar to the excerpt above, exceptthat the method sets thepm_classname andpe_classname fields tothe special valueno_class. This indicates to TME 10 that the record isnot directly associated with a profile object.137 /* Set the values of the validation record */

138 pvr.pm_classname =

139 pvr.pe_classname = TMF_CCMS_Database_no_class;

140 pvr.flags = 0;

141 pvr.parent = pdr_record_key;

142 pvr.validation = OBJECT_NIL;

143 pvr.partition = pdr_record_key;

144 pvr_obj_label.label = "";

145 pdr_obj_label.objref = OBJECT_NIL;

146

147 /* Add the validation record to the new profile */

148 t_TMF_CCMS_Database_add_record(

149 profile_organizer, &bogus_env,

150 Trans_sub, db_name, pvr_record_key,

151 &pvr, &pvr_obj_label);

Finally, theinitializ method must set the values of various attributeson the profile object. The table below shows the standard writableattributes of a profile.

Attribute Purpose

the_context Indicates whether the profile exists within aprofile manager or an endpoint

profile_organizer Contains the object reference of the profilemanager or endpoint

db_name Holds the name of the profile database

record_key Contains the key of a record associated withthe profile

partition Contains the name of the partition used bythe profile

default_push_params Sets the default distribution behavior

Page 89: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The initializ Method

Application Development with TME 10 ADE 3–9

Method Im

plementations

152 _t_imp_TPL_PhoneListProfile__set_the_context(

153 _TPL_PhoneListProfile, &bogus_env, a_context);

154

155 _t_imp_TPL_PhoneListProfile__set_profile_organizer(

156 _TPL_PhoneListProfile, &bogus_env,

157 profile_organizer);

158

159 _t_imp_TPL_PhoneListProfile__set_db_name(

160 _TPL_PhoneListProfile, &bogus_env, db_name);

161

162 _t_imp_TPL_PhoneListProfile__set_record_key(

163 _TPL_PhoneListProfile, &_env, pdr_record_key);

164 , &_env, pdr_record_key);

165

166 _t_imp_TPL_PhoneListProfile__set_partition(

167 _TPL_PhoneListProfile, &bogus_env, pdr_record_key);

168

169 /*Set the default values for push level and type */

170 push_params.flags =

171 TMF_CCMS_Propagation_initial_merge;

172 push_params.one_step = TRUE;

173 _t_imp_TPL_PhoneListProfile__set_default_push_params(

174 _TPL_PhoneListProfile, &bogus_env, &push_params);

175 }

The attributethe_context indicates whether the profile exists in thecontext of a profile manager or aprofile_endpoint. The attribute’svalue is passed to theinitializ method as a parameter by TME 10.

Theprofile_organizer attribute contains the object reference of theprofile manager or profile endpoint where the profile resides. Theobject reference of the profile organizer is very important, since allmethods that interact with the profile’s database reside on the profileorganizer.

Thedb_name attribute holds the name of the profile database. Thepartition attribute holds the name of the database partition thatcontains the records associated with the profile. Tivoli/Phone uses thekey of the default policy record as its partition, since it contains theprofile object reference and is therefore unique among profiles.

Page 90: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The initializ Method

3–10 Version 3.6

Therecord_key attribute contains the key of the record that is directlyassociated with the profile. As you read earlier, CCMS uses theassociated record to get information about the behavior of the profile.Tivoli/Phone stores the key of the default record in this attribute, sinceit is guaranteed to exist in the profile database.

Thedefault_push_params attribute controls the default behavior ofCCMS when the profile is distributed to subscribers. The value of theattribute is a type calledpush_params, which has two fields:flags andone_step. Theflags field is an enumerated data type that controlswhether TME 10 overwrites modifications to the local profile during adistribution. Tivoli/Phone sets theflags field tono_force, whichprevents locally modified records from being overwritten by data fromthe source profile.

Theone_step flag controls whether CCMS distributes the profile tothe next level of subscribers (TRUE) or to all levels of subscribers(FALSE). One interesting side effect of theone_step flag is that anendpoint and its endpoint method are considered two separate levels.So, if you push to an endpoint whenone_step is TRUE, it updatesonly the profile database on the endpoint; it does not execute theendpoint method. You must haveone_step set toFALSE if you wantto execute the profile’s endpoint method.

Creating Initial Default and Validation PolicyOne of the primary functions of theinitializ method is to create thedefault and validation policy records for the new profile. If the newprofile is being cloned from an existing object,initializ can use thepolicy records from the source profile. Otherwise, the method mustcreate policy records from scratch.

The Tivoli/Phone application’sinitializ method creates the policyrecords for the new profile, but does not specify any actual policy.Instead, the application initially sets all policy attributes to “don’tcare.” An excerpt frominit_default_val_rec, which initializes thedefault policy attributes, is shown below. The code for initializingvalidation policy attributes is similar.1 void init_default_val_rec(

2 TPL_PhoneListProfile o,

3 TMF_CCMS_Database_nmval_list *attrs)

Page 91: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The initializ Method

Application Development with TME 10 ADE 3–11

Method Im

plementations

4 {

5 ml_t *mh = ml_create();

6 char *empty = "";

7 char **tmp_str;

8

9 /* Initialize all the attributes to “don’t care” and set

10 * their values to be empty string constants. This

11 * means there is initially no policy for the profile.

12 */

13 tmp_str = mg_malloc(sizeof(*tmp_str));

14 *tmp_str = mg_strdup(empty);

15 add_nmval_value(attrs, PHONELIST_NAME_FIELD,

16 TMF_CCMS_Database_dont_care,

17 TC_string, tmp_str);

18 /* Set the phone attribute to “don’t care” so the

19 * user has to supply their own value.

20 */

21

22 tmp_str = mg_malloc(sizeof(*tmp_str));

23 *tmp_str = mg_strdup(empty);

24 add_nmval_value(attrs, PHONELIST_PHONE_FIELD,

25 TMF_CCMS_Database_dont_care,

26 TC_string, tmp_str);

27

28

29 tmp_str = mg_malloc(sizeof(*tmp_str));

30 *tmp_str = mg_strdup(empty);

31 add_nmval_value(attrs, PHONELIST_ADDRESS_FIELD,

32 TMF_CCMS_Database_dont_care,

33 TC_string, tmp_str);

34 ...

35 }

The function uses an application function calledadd_nmval_value tocreate annmval structure for each policy attribute. The function alsosets thedont_care flag, which CCMS checks before enforcing policy

Page 92: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The initializ Method

3–12 Version 3.6

on an attribute. CCMS does not enforce policy on an attribute if itsdont_care flag is set.

If you want to provide initial policy with your application, the code isvery similar. For example, to provide a constant-value policy for anattribute, you simply insert a string in place of theempty string.

*tmp_str = mg_strdup(CORPORATE_ADDRESS);add_nmval_value(attrs, PHONELIST_ADDRESS_FIELD, 0, TC_string, tmp_str);

If your application provides script-valued policy for an attribute, thecode is only slightly more complicated. With a script-valued policy,the body of the script and arguments are stored in the record’s attributewith the type codeTC_TMF_CCMS_Database_script. You mustalso specify the return type of the script (TC_string for shell scripts).

/* Set the return type to string */script->type = TC_string;

/* Get the script arguments and body based on the * field we are setting policy for */script->args = init_script_args(PHONELIST_ADDRESS_FIELD);script->body = read_script(PHONELIST_ADDRESS_FIELD);

/* Add the policy to the policy record */add_nmval_value(attrs, PHONELIST_ADDRESS_FIELD, 0, TC_TMF_CCMS_Database_script, body);

The dont_care FlagCCMS interprets thedont_care flag differently on validation anddefault policy records. On a validation policy attribute, thedont_careflag controls whether CCMS should enforce validation policy on theattribute. On a default policy attribute, thedont_care flag means thatthere is no policy available for the attribute. The user must supply avalue for any attribute whose corresponding default policy attribute hasthedont_care flag set.

Page 93: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Representing Application Data

Application Development with TME 10 ADE 3–13

Method Im

plementations

Representing Application DataProfile records are stored in a format defined by theTMF_CCMS::Database::record data structure. Although you cancertainly use this structure when dealing with a record, you may findit easier to convert the record to your own data structure. There are acouple of advantages to using your own data structure. The firstadvantage is memory usage. The CCMS record structure incurs a largeamount of memory overhead for storing record flags and data, most ofwhich is unused by the application. Converting the record to anapplication-specific structure eliminates much of the overhead bysaving only the data your application needs.

The second advantage is that, from a client point-of-view, theapplication data is abstract with respect to its implementation. So, aclient can call thecreate_phone_entry method without having toknow whether the application uses CCMS or some other mechanism.The method implementation converts between the CCMS recordformat and the application data structure.

For example, the Tivoli/Phone application uses a data structure calledPhoneEntryInfo, which is defined in the application’s IDL definition.The structure maintains the values of a record’s attributes, as well ascertain state information. The structure’s IDL definition is shownbelow.

struct PhoneEntryInfo { unsigned long flags; boolean fixed; boolean read_only; string name; string phone; PhoneOwner owner; PhoneType type; string address; string city; string state; string country; string postal; string comment; AEFAttrList aef_attrs;};

Page 94: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Representing Application Data

3–14 Version 3.6

The application provides convenience functions so that methods canconvert to and from the CCMS record format. In the Tivoli/Phoneapplication, these are theconvert_nmval_to_entry andconvert_entry_to_nmval functions.

Theconvert_nmval_to_entry function takes a sequence of attributesfrom a profile record (thenmval_list data structure) and converts it tothe application data structure. An excerpt of the function is shownbelow.1 void convert_nmval_to_entry(

2 TMF_CCMS_Database_nmval_list *list,

3 TPL_PhoneEntryInfo *entry)

4 {

5 TMF_CCMS_Database_nmval *p;

6 int i;

7 char **tmp;

8 char *str = NULL;

9 Environment ev = {0};

10

11 for (i = 0; i < seq_len((sequence_t *)list); i++) {

12 p = (TMF_CCMS_Database_nmval *)

13 seq_get((sequence_t *)list, i,

14 sizeof(TMF_CCMS_Database_nmval));

15

16 ...

17

18 if (strcmp(p->name, PHONELIST_NAME_FIELD) == 0) {

19 entry->name = str;

20 }

21 else if (strcmp(p->name, PHONELIST_NAME_FIELD)

22 == 0) {

23 entry->phone = str;

24 }

25

26 ...

27

28 else if (strcmp(p->name, PHONELIST_TYPE_FIELD)

29 == 0) {

30 entry->type = *(TPL_PhoneType *)

31 p->data._value;

32 }

Page 95: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Representing Application Data

Application Development with TME 10 ADE 3–15

Method Im

plementations

33

34 /* It must be an AEF attribute */

35 else {

36 TPL_AEFAttr aef_attr;

37

38 aef_attr.name = mg_strdup(p->name);

39 aef_attr.value = str;

40 seq_add((sequence_t *)&entry->aef_attrs,

41 &aef_attr,

42 sizeof(TPL_AEFAttr));

43 }

44 }

45 }

The function iterates through the sequence of attributes, checks theattribute’s name, and assigns the attribute’s value to the appropriatefield of the structure.

If there are any attributes that do not have one of the expected names,the function assumes they are custom attributes added with TME 10AEF. The function stores the names and values of these attributes in aspecial sequence on the application data structure (theaef_attrs field).

Theconvert_entry_to_nmval function reverses the process ofconvert_nmval_to_entry. This function takes an application datastructure and creates a sequence of CCMS record attributes.An excerpt from the function is shown below.1 void convert_entry_to_nmval(

2 TPL_PhoneEntryInfo *info,

3 TMF_CCMS_Database_nmval_list *list)

4 {

5 void *tmp;

6 char **tmp_str;

7

8 tmp_str = mg_malloc(sizeof(*tmp_str));

9

10 /*

11 * If none of the fields were set, don't bother

12 */

13 if (info->flags == 0) {

14 return;

15 }

16

Page 96: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Creation

3–16 Version 3.6

17 if (info->flags & TPL_PP_NAME_FLAG) {

18 tmp_str = mg_malloc(sizeof(*tmp_str));

19 *tmp_str = mg_strdup(info->name);

20 add_nmval_value(list, PHONELIST_NAME_FIELD,

21 0, TC_string, tmp_str);

22 }

23

24 if (info->flags & TPL_PP_PHONE_FLAG) {

25 tmp_str = mg_malloc(sizeof(*tmp_str));

26 *tmp_str = mg_strdup(info->phone);

27 add_nmval_value(list, PHONELIST_PHONE_FIELD,

28 0, TC_string, tmp_str);

29 }

30

31 ...

32

33 if (info->flags & TPL_PP_COMMENT_FLAG) {

34 tmp_str = mg_malloc(sizeof(*tmp_str));

35 *tmp_str = mg_strdup(info->comment);

36 add_nmval_value(list,

37 PHONELIST_COMMENT_FIELD,

38 0, TC_string, tmp_str);

39 }

40

41 ...

42

43 }

ThePhoneEntryInfo structure includes a set of flags that indicatewhich fields in the structure have changed since the last time the recordwas updated from CCMS. Theconvert_entry_to_nmval functionuses these flags to determine which fields it must convert intonmvalstructures.

Record CreationOnce you have implemented your class’sinitializ method and cancreate instances of the class, the next logical step is to implement amethod that can add records to the profile.

The Tivoli/Phone application has three operations that can createrecords in a phone profile:

Page 97: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Creation

Application Development with TME 10 ADE 3–17

Method Im

plementations

■ create_phone_entry

■ create_phone_entries

■ populate

In this section, we discuss thecreate_phone_entry method. Thecreate_phone_entries method takes advantage of some fairlysophisticated TME 10 ADE services, so we will postpone discussingit until the end of this chapter.

Thepopulate operation automatically generates profile records basedon “live data” such as a system file. Your profile class inheritspopulate from theTMF_CCMS::Profile interface. You can find adiscussion of the Tivoli/Phone implementation ofpopulate in Chapter4, “Implementations for CCMS Methods.”

Thecreate_phone_entry adds a single entry to the phone list. TheIDL signature ofcreate_phone_entry is shown below.

void create_phone_entry(in TPL::PhoneEntryInfo entry, out string key);

Thecreate_phone_entry method takes aPhoneEntryInfo structureand creates a CCMS record for it. The method returns the key of thenew record to the client as an output parameter.

Before it can convert the structure into a CCMS record, the methodensures that thePhoneEntryInfo structure at least has the name andphone fields set. If either of the fields is missing, the method throws anexception, since the application creates the record key from the twofields.1 void t_imp_TPL_PhoneListProfile_create_phone_entry(

2 TPL_PhoneListProfile o,

3 Environment *_ev,

4 transaction _transaction,

Parameter Description

entry An application structure containing the information forthe new record

key The key of the new record (output parameter)

Page 98: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Creation

3–18 Version 3.6

5 TPL_PhoneEntryInfo *new_entry,

6 char **key)

7 {

8 Object profile_org;

9 TMF_CCMS_Database_record rec;

10 ml_t *mh = ml_create();

11 char *def_rec_key, *val_rec_key;

12 void **key_handle;

13 SysAdminTypes_ObjectLabel rec_obj_label;

14 char *db_name = PHONELIST_DBNAME;

15 any notice_any;

16 TMF_Types_StringList notice_data;

17 char *profile_name;

18 tmf_msg_t *msg;

19

20 /*

21 * Make sure that the new entry has the name and phone

22 * fields set, since we need them to make a key.

23 */

24 if (new_entry->name == NULL || strlen

25 (new_entry->name) == 0 ||new_entry->phone

26 == NULL || strlen(new_entry->phone) == 0)

27 {ExPhoneError *ex = (ExPhoneError

28 *)ExPhoneErrorNew(phone_msgs,

29 missing_req_fields);

30 Throw(ex->type_name, ex);

31 }

32

33 }

Next, the method gets the profile’s profile organizer object and sets theCCMS database record for the new entry. In the code excerpt below,the method sets the new record’s default and validation policy records,sets the partition name, and initializes the record’s flags. The functionalso initializes anObjectInfo structure, which is a parameter to theTMF_CCMS::Database::add_record method.34 /*

35 * Get the profile’s profile organizer object

36 */

37 profile_org =_t_imp_TPL_PhoneListProfile__get_profile_organizer

38 (o, _ev);

Page 99: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Creation

Application Development with TME 10 ADE 3–19

Method Im

plementations

39 ml_attach_Object_reference(mh, profile_org);

40

41

42 /* Make keys for the record’s parent and validation

43 * records

44 */

45 def_rec_key = get_def_rec_key(o);

46 ml_attach_addr(mh, def_rec_key);

47 val_rec_key = get_val_rec_key(o);

48 ml_attach_addr(mh, val_rec_key);

49

50 /* Set up the new record's fields */

51 memset(&rec, 0, sizeof(TMF_CCMS_Database_record));

52 rec.pm_classname = TMF_CCMS_Database_no_class;

53 rec.pe_classname = TMF_CCMS_Database_no_class;

54 rec.flags = 0;

55 rec.partition = def_rec_key;

56 rec.parent = OBJECT_NIL;

57 rec.validation = OBJECT_NIL;

58 rec.validation = val_rec_key;

59 rec_obj_label.label = "";

60 rec_obj_label.objref = OBJECT_NIL;

The method calls two functions (lines 45 and 47) to retrieve the keysto the default and validation policy record.

TheObjectInfo structure initialized on lines 59 and 60 associates anobject with the record. In an application where each profile record isassociated with an object, this structure contains the object referenceof the associated object. The Tivoli/Phone application does notassociate an object with each record, so the method sets this structureto OBJECT_NIL .

At this point, the method is nearly ready to add the new record to theprofile database. The method constructs a unique key for the recordand converts thePhoneEntryInfo structure into annmval_listsequence. The method then calls theTMF_CCMS::Database::add_record method on the profileorganizer object to add the record to the profile database.61 /*

62 * Make a key for the new record.

63 */

Page 100: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Creation

3–20 Version 3.6

64 *key = make_record_key(new_entry);

65 key_handle = ml_attach_addr(mh, *key);

66

67 convert_entry_to_nmval(new_entry, &rec.attrs);

68 ml_attach_struct(mh, &rec.attrs, free_nmvals);

69

70 if (seq_len((sequence_t *)&rec.attrs) == 0) {

71 ExPhoneError *ex = (ExPhoneError *)ExPhoneErrorNew(

72 phone_msgs,

73 missing_req_fields);

74 Throw(ex->type_name, ex);

75 }

76

77 Try {

78 ccms_add_record_with_aef(profile_org,_ev,Trans_sub,

79 db_name,

80 *key,

81 &rec,

82 &rec_obj_label);

83 }

84 CatchOne(ExExists) {

85 ExPhoneError *ex =(ExPhoneError *)ExPhoneErrorNew(

86 phone_msgs,

87 entry_exists);

88 Throw(ex->type_name, ex);

89 }

90 CatchOne(ExException) {

91 ExPhoneError1 *ex =(ExPhoneError1 *)ExPhoneError1New(

92 phone_msgs,

93 create_

94 failed,

95 new_entry->name);

96 ContextThrow(ex->type_name, ex);

97 }

98 EndTry;

99

Page 101: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Creation

Application Development with TME 10 ADE 3–21

Method Im

plementations

In the code excerpt above, the method handles two error conditionsthat can result from callingadd_record. If theadd_record methodthrows anExExists error, the method catches it (line 84) and throwsits own error to indicate that there is already a record with the givenkey. Thecreate_phone_entry method handles any exception otherthanExExists by catchingExException on line 90. The methodcreates its own context error message and usesContextThrow toattach it to the exception thrown byadd_record.

If create_phone_entry successfully adds the new profile record, themethod logs a notice to the application’s notice group about the newrecord. The notice in this case takes two variables: the name of the newentry and the name of the profile. A C-locale example of the notice isshown below.

Added an entry for Augustus Caesar to the BlackBook profile.

The code fragment below shows how to log the creation notice.100 /*

101 * Set up the data for the notice. The notice data is

102 * a StringList sequence that contains the entry name

103 * and the profile name.

104 */

105 memset(&notice_any, 0, sizeof(notice_any));

106 seq_init((sequence_t *)&notice_data);

107 notice_any._type = TC_TMF_Types_StringList;

108 seq_add((sequence_t *)&notice_data,&new_entry->name,sizeof(char *));

109 seq_add((sequence_t *)&notice_data,&profile_name,sizeof(char *));

110 notice_any._value = &notice_data;

111

112 /*

113 * Log the notice.

114 */

115 msg = tmfMsgNew(phone_msgs, new_entry_notice,notice_any);

116

117 tmf_msg_log(msg, NOTICE_GROUP, TMF_Notice_Notice);

Page 102: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Retrieval

3–22 Version 3.6

118 tmf_msg_destroy(msg);

119

120 *key = ml_detach(mh, key_handle);

121 ml_destroy(mh);

122 }

123

In the example above, the entry name and profile name are loaded intoa StringList sequence. Then, the sequence is wrapped in ananystructure (lines 107 and 110). The function then creates and logs thenotice message, using theany as a data parameter.

Record RetrievalTivoli/Phone provides two methods for retrieving specific recordsfrom the profile database:get_phone_entry andget_phone_entries.The former takes a single record key and returns the associated record.The latter takes a sequence of keys and returns a sequence of theassociated records. The IDL signatures for both methods are shownbelow.

void get_phone_entry(in string key, out PhoneEntryInfo entry)

void get_phone_entries(in TMF_Types::StringList keys, out PhoneEntryInfoList entries)

Why have two methods when theget_phone_entries method issufficient for both cases? The answer is thatget_phone_entry is aconvenience method so that a client can get a single record withoutgoing to the effort of building a single-element sequence. TheTivoli/Phone implementation of the two methods are built around asingle function that retrieves the records, so there is very littleadditional code for two methods.

A routine calledreal_get_entry underlies both retrieval methods. Thisfunction takes a profile object reference and a record key, retrieves therecord, and converts it to an application-specific data structure. Thefunction uses theTMF_CCMS::Database::get_record method onthe profile organizer to pull the record from the profile database.1 void real_get_entry(Object profile_org,

2 char *dbname,

Page 103: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Retrieval

Application Development with TME 10 ADE 3–23

Method Im

plementations

3 char *key,

4 TPL_PhoneEntryInfo *entry)

5 {

6 TMF_CCMS_Database_record rec;

7 ml_t *mh = ml_create();

8 Environment ev = {0};

9

10 memset(&rec, 0, sizeof(TMF_CCMS_Database_record));

11 memset(entry, 0, sizeof(TPL_PhoneEntryInfo));

12

13 /* Get the profile organizer reference */

14 profile_org =

15 _t_imp_TPL_PhoneListProfile__get_profile_organizer(

16 o,

17 _ev);

18 ml_attach_Object_reference(mh, profile_org);

19

20 /* Get the database name from the profile */

21

22 db_name =

23 t_imp_TPL_PhoneListProfile__get_db_name(

24 profile,

25 _ev);

26 ml_attach_addr(mh, db_name);

The function attaches the object reference and the database name to alocal memory handle (lines 18 and 26). The local memory handle(created on line 7) provides a way to prevent memory leaks if anexception occurs. If an exception occurs while the function isexecuting, the local memory handle frees all the memory attached toit. If the function completes successfully,real_get_entry callsml_destroy to destroy the local handle and free its memory. You willencounter this form of memory management throughout theTivoli/Phone application.

The next part of the function uses theDatabase::get_record methodon the profile organizer to retrieve the specified record.27 /* Get the database record for the key */

28 Try {

29 t_TMF_CCMS_Database_get_record(

30 profile_org, &ev, Trans_sub,

31 db_name, key, FALSE, &rec);

Page 104: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Retrieval

3–24 Version 3.6

32 ml_attach_ORB_output(mh, &rec);

33 }

34 Catch(ExNotFound, ex) {

35 ExPhoneError1 *ex1 = (ExPhoneError1 *)

36 ExPhoneError1New(phone_msgs,

37 get_failed, key);

38 Throw(ex1->type_name, ex1);

39 }

40 EndTry;

The method call is made from within aTry /Catch block. Ifget_record throws anExNotFound exception (because it could notlocate a record with the given key), thereal_get_entry catches it andthrows an application-specific error message.

Finally, real_get_entry converts the CCMS record into theapplication’sPhoneEntryInfo data structure.41 /* Convert the record to an entry */

42 convert_nmval_to_entry(&rec.attrs, entry);

43

44 /*

45 * Set the fixed and read-only flags on

46 * the structure to reflect the record.

47 */

48 if (rec.flags & TMF_CCMS_Database_r_readonly) {

49 entry->read_only = TRUE;

50 }

51

52 if (rec.flags & TMF_CCMS_Database_r_fixed) {

53 entry->fixed = TRUE;

54 }

55

56 /* Release the attached memory */

57 ml_destroy(mh);

58 }

The function usesconvert_nmval_to_entry (discussed earlier in thischapter) to convert the CCMS record’s list of attributes into theapplication’s own data structure. The function also preserves theCCMS record’s state flags in the application structure (lines 48–54).In this case, the application saves ther_readonly andr_fixed recordflags.

Page 105: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Retrieval

Application Development with TME 10 ADE 3–25

Method Im

plementations

The method implementations ofget_phone_entry andget_phone_entries are built on top of thereal_get_entry core. In thecase ofget_phone_entry, the method implementation just provides abasic wrapper for a call toreal_get_entry.1 void t_imp_TPL_PhoneListProfile_get_phone_entry(

2 TPL_PhoneListProfile o,

3 Environment *_ev,

4 transaction _transaction,

5 char *key,

6 TPL_PhoneEntryInfo *entry)

7 {

8 real_get_entry(profile_org, db_name, key, entry);

9 }

The implementation returns thePhoneEntryInfo structure obtainedby callingreal_get_entry since this method is functionally identicalto real_get_entry.

The implementation forget_phone_entries is only slightly morecomplicated. It must iterate over a list of keys, callreal_get_entry,and build a output sequence.1 void t_imp_TPL_PhoneListProfile_get_phone_entries(

2 TPL_PhoneListProfile o,

3 Environment *_ev,

4 transaction _transaction,

5 TMF_Types_StringList* keys,

6 TPL_PhoneEntryInfoList* entries)

7 {

8 TPL_PhoneEntryInfo entry;

9 char **key = NULL;

10 int i, num_entries;

11 ml_t *mh = ml_create();

12 Object profile_org;

13 char *db_name, *def_key, *val_key;

14

15 seq_init((sequence_t *)entries);

16

17 /*

18 * Get the default and validation record keys so we

19 * can skip them.

20 */

21 def_key = get_def_rec_key(o);

Page 106: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Retrieval

3–26 Version 3.6

22 ml_attach_addr(mh, def_key);

23 val_key = get_val_rec_key(o);

24 ml_attach_addr(mh, val_key);

25

26 /*

27 * Get the profile manager for the profile and attach

28 * it to the local memory handle so it gets cleaned up

29 * at the end.

30 */

31 profile_org =

32 _t_imp_TPL_PhoneListProfile__get_profile_organizer(

33 o,

34 _ev);

35 ml_attach_Object_reference(mh, profile_org);

36

37 /* Get the database name from the profile */

38 db_name = _t_imp_TPL_PhoneListProfile__get_db_name

39 (o, _ev);

40 ml_attach_addr(mh, db_name);

41

42 num_entries = seq_len((sequence_t *)keys);

43 for (i = 0; i < num_entries; i++) {

44 key = (char **)seq_get((sequence_t *)keys,

45 i, sizeof(char *));

46

47 real_get_entry(profile_org, db_name,

48 *key, &entry);

49

50 /* Add it to the return sequence */

51 seq_add((sequence_t *)entries,

52 &entry, sizeof(TPL_PhoneEntryInfo));

53 }

54

55 ml_destroy(mh);

56 }

You can reduce the amount of application code and increase itsmaintainability by allowing similar methods to share a commonengine.

Page 107: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Deletion

Application Development with TME 10 ADE 3–27

Method Im

plementations

Record DeletionSimilar to the methods used to create and retrieve records,Tivoli/Phone provides two operations to delete records.Thedelete_phone_entry operation deletes a single record.Thedelete_phone_entries operation allows a client to delete multiplerecords with a single method call.

Like the record-retrieval methods, the implementations ofdelete_phone_entry anddelete_phone_entries share a single enginethat does the actual work of removing records.

The implementation for thedelete_phone_entries method is just awrapper for thereal_delete function, since they both take a sequenceof record keys.1 void t_imp_TPL_PhoneListProfile_delete_phone_entries(

2 TPL_PhoneListProfile o,

3 Environment *_ev,

4 transaction _transaction,

5 char *key)

6 {

7 real_delete(o, _ev, keys);

8 }

The implementation fordelete_phone_entry is equallystraightforward. The method places itskey parameter into aStringListsequence and callsreal_delete.1 void t_imp_TPL_PhoneListProfile_delete_phone_entry(

2 TPL_PhoneListProfile o,

3 Environment *_ev,

4 transaction _transaction,

5 char *key)

6 {

7 ml_t *mh = ml_create();

8 TMF_Types_StringList keys;

9

10 /* Stuff the key into a string sequence */

11 seq_init((sequence_t *)&keys);

12 seq_add((sequence_t *)&keys, &key, sizeof(char *));

13

14 real_delete(o, _ev, &keys);

15

Page 108: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Deletion

3–28 Version 3.6

16 seq_free_buffer((sequence_t *)&keys);

17 ml_destroy(mh);

18 }

After thereal_delete function has completed, the methodimplementation fordelete_phone_entry frees the memory allocatedfor the temporary sequence and terminates.

The real_delete function takes the sequence of keys and uses theTMF_CCMS::Database::delete_record method on the profileorganizer to remove each record. Before it can delete the records,however,real_delete must get the information it needs to call thedelete_record method. To do this, the function retrieves the objectreference of the profile organizer and the name of the database fromthe attributes on the profile object.1 static void real_delete(

2 TPL_PhoneListProfile o,

3 Environment *_ev,

4 TMF_Types_StringList *keys)

5 {

6 Object profile_org;

7 ml_t *mh = ml_create();

8 char *db_name; *profile_name;

9 char ** volatile key;

10 int volatile i;

11 int volatile num_recs;

12 any arg, arg2;

13 TMF_Types_StringList notice_data;

14 tmf_msg_t *msg;

15

16 /* Get the profile’s profile organizer object */

17 profile_org =

18 _t_imp_TPL_PhoneListProfile__get_profile_organizer(

19 o, _ev);

20 ml_attach_Object_reference(mh, profile_org);

21

22 db_name =

23 _t_imp_TPL_PhoneListProfile__get_db_name(

24 o, _ev);

25 ml_attach_addr(mh, db_name);

Page 109: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Deletion

Application Development with TME 10 ADE 3–29

Method Im

plementations

The function attaches the object reference and database name to a localmemory handle, which is destroyed at the end of the function. Whenthe memory handle is destroyed, it automatically frees the memoryattached to it.

After it has obtained the profile organizer reference and the databasename,real_delete iterates over the sequence of keys, running thedelete_record method on the profile organizer to remove each record.26 num_recs = seq_len((sequence_t *)keys);

27 for (i = 0; i < num_recs; i++) {

28

29 key = (char **)seq_get((sequence_t *)keys,

30 i, sizeof(char *));

31

32 ccms_delete_record_with_aef(profile_org,

33 _ev,

34 Trans_sub,

35 db_name,

36 *key);

37 }

After the function has deleted the records, it logs a notice with theTME 10 notice registry to indicate which records were deleted.Tivoli/Phone logs a single notice that lists all the deleted records. Youcould just as easily log a separate notice for each record, but collatingsimilar notices into a single summary notice can improve usability andis more scalable.38 profile_name =

39 _t_imp_TPL_PhoneListProfile__get_label(

40 o, _ev);

41 ml_attach_addr(mh, profile_name);

42

43 /* Create a message for the notice header */

44 memset(&arg, 0, sizeof(arg));

45 seq_init((sequence_t *)&notice_data);

46 arg._type = TC_TMF_Types_StringList;

47 seq_add((sequence_t *)&notice_data, &profile_name,

48 sizeof(char *));

49 arg._value = &notice_data;

50 msg = tmfMsgNew(phone_msgs, del_header_notice, arg);

51

52 /* Put the list of keys into a nested message*/

Page 110: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Modification Method

3–30 Version 3.6

53 memset(&arg2, 0, sizeof(arg2));

54 arg2._type = TC_TMF_Types_StringList;

55 arg2._value = keys;

56 tmfMsgAdd(msg, phone_msgs,

57 key_list, arg2, 1);

58

59 /* Log the notice */

60 tmf_msg_log(msg, NOTICE_GROUP, TMF_Notice_Notice);

61 tmf_msg_destroy(msg);

62

63 ml_destroy(mh);

64 }

The real_delete function’s summary notice is an aggregate of twomessages: a header message and a message that contains a list ofrecord keys. The message catalog entries for the two messages areshown below.

$ key=del_header_notice145 Removed the following entries from the %1$s profile:

$ key=keylist146 %0$I{ %1$s\n}

The function uses thetmfMsgAdd macro to combine the twomessages into a single aggregate message.

Removed the following entries from the BlackBook profile: Augustus Caesar Manny Mota Johnny Cash

The ability to combine messages allows you to create messageprimitives and use them in multiple places. In Tivoli/Phone, forexample, thekeylist message is used to create any notice to list asequence of strings.

Record Modification MethodContinuing with the implementation of the core group of methods, ournext task is to implement a method to modify an existing profilerecord. In the Tivoli/Phone, the method that changes a record’s

Page 111: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Modification Method

Application Development with TME 10 ADE 3–31

Method Im

plementations

attributes is calledmodify_phone_entry. The method’s IDL signatureis shown below.

void modify_phone_entry(in string key, in TPL::PhoneEntryInfo entry)

The implementation ofmodify_phone_entry must verify two thingsbefore it can update the specified record:

■ The name and phone number fields of the structure have notchanged.

■ The record is not read-only in the correct context.

Tivoli/Phone enforces the first condition because the application usesthe name and phone number to construct the record key. Thisrestriction is somewhat arbitrary and only serves to simplify theexample. It is a fairly simply matter to write the modify method so thatit is capable of changing the record key.

The second condition refers to the ability of a user to mark a record as“fixed.” A fixed record cannot be locally modified by a subscriber.When a fixed record is distributed to subscribers, it is marked asread-only in the local database. The implementations of your methodsthat modify records in the profile database must honor the read-onlyrestriction.1 void t_imp_TPL_PhoneListProfile_modify_phone_entry(

2 TPL_PhoneListProfile o,

3 Environment *_ev,

4 transaction _transaction,

5 char *key,

6 TPL_PhoneEntryInfo *entry)

7 {

8

9 Object profile_org;

10 char *db_name;

11 TMF_CCMS_Database_nmval_list new_vals;

12 TMF_CCMS_Database_record rec;

13 ml_t *mh = ml_create();

14

15 /*

16 * If none of the fields of the structure are set,

17 * just exit.

Page 112: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Modification Method

3–32 Version 3.6

18 */

19 if (entry->flags == 0) {

20 ml_destroy(mh);

21 return;

22 }

23

24 /* Make sure no one is trying to change

25 * the name or phone field.

26 */

27 if (entry->flags & TPL_PP_NAME_FLAG ||

28 entry->flags & TPL_PP_PHONE_FLAG) {

29 ExPhoneError *ex = (ExPhoneError *)

30 ExPhoneErrorNew(phone_msgs,

31 no_name_change);

32 Throw(ex->type_name, ex);

33 }

34

35 ...

36

37 t_TMF_CCMS_Database_get_record(

38 profile_org, _ev, Trans_sub,

39 db_name, key, FALSE, &rec);

40

41 /*

42 * Make sure this record can be edited

43 * in the current context.

44 */

45 if (rec.flags & TMF_CCMS_Database_r_readonly) {

46 ExPhoneError *ex =

47 (ExPhoneError *)ExPhoneErrorNew(

48 phone_msgs, fixed_in_context);

49 Throw(ex->type_name, ex);

50 }

The method reads the specified profile record from the database usingtheTMF_CCMS::Database::get_record method on the profileorganizer. It then examines ther_readonly flag on the record to see ifthe record is read-only in the current context. If the record is read-only,modify_phone_entry throws an exception to inform the caller that therecord cannot be changed.

Page 113: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Modification Method

Application Development with TME 10 ADE 3–33

Method Im

plementations

If the record can be edited,modify_phone_entry converts thePhoneEntryInfo structure into annmval_list sequence using theconvert_entry_to_nmval function. The method then runs theTMF_CCMS::Database::set_values method on the profile organizerobject to write the new attribute values to the existing CCMS record.51 /* Create an nmval list for the values */

52 convert_entry_to_nmval(entry, &new_vals);

53

54 /*

55 * Write the new values to the record. The create flag is

56 * set to FALSE, since the record should already have

57 * all the attributes.

58 */

59

60 if (seq_len((sequence_t *)&new_vals) > 0) {

61 ccms_set_values_with_aef(

62 profile_org, _ev, Trans_sub,

63 db_name, key, &new_vals, FALSE);

64 }

The method also changes the state of the record flags if it is necessary.The Tivoli/Phone application only tracks the state of the record’sr_fixed flag, which controls whether subscribers can edit their copy ofthe record. Thefixed field of thePhoneEntryInfo structure containsthe state of the record’sr_fixed flag. If the state of the flag haschanged, the method runs theset_record_flags method on the profileorganizer to change ther_fixed flag on the CCMS record.65 /* Set/clear the fixed flag if changed */

66 if (entry->flags & TPL_PP_FIXED_FLAG) {

67 t_TMF_CCMS_Database_set_record_flags(

68 profile_org, _ev, Trans_sub,

69 db_name, key, TMF_CCMS_Database_r_fixed,

70 entry->fixed);

71 }

72 }

ThePhoneEntryInfo structure contains a flag calledTPL_PP_FIXED_FLAG that is set whenever the state of thefixedfield changes. The method examines this flag (line 66) to determine ifit must change ther_fixed flag on the profile record.

Page 114: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Record Modification Method

3–34 Version 3.6

Page 115: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Development with TME 10 ADE 4–1

Implem

entations forC

CM

S M

ethods

4Implementations for CCMSMethods

TheTMF_CCMS::Profile interface, which all profile objects inherit,defines numerous operations for managing a profile object. You caninherit implementations for most, but not all, of the operations throughthe imp_TMF_CCMS::Profile abstract class. Some profileoperations require application-specific behavior, so standardimplementation is not possible. TME 10 ADE does not provideimplementations for the following operations:

■ initializ

■ get_default_policies

■ set_default_policies

■ get_validation_policies

■ set_validation_policies

■ enable_validation

■ disable_validation

■ validate

■ populate

■ move_records

■ copy_records

4

Page 116: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Policy-related Methods

4–2 Version 3.6

Tivoli/Phone’s profile-based class,PhoneListProfile, inherits fromTMF_CCMS::Profile , so it must provide implementations for theabove operations. In addition, thePhoneListProfile class overridesthe standard implementation of theremove method with one of itsown. Tivoli/Phone’s implementation of theinitializ method is coveredin Chapter 3, “Method Implementations.” This chapter covers theimplementations of the other CCMS-defined operations.

For a more in-depth discussion of CCMS, refer to theApplicationServices Manual, Vol. II.

Policy-related MethodsOne of the primary features of a profile-based application is that thesupport for policy—both default and validation—is built into theprofile. When a class inheritsTMF_CCMS::Profile , it inherits anumber of methods that provide profile policy. TheProfile interfaceprovides seven policy-related methods:

■ get_default_policies

■ set_default_policies

■ get_validation_policies

■ set_validation_policies

■ enable_validation

■ disable_validation

■ validate

Changing Profile PolicyYour profile inherits four methods fromTMF_CCMS::Profile thatallow you to retrieve and set profile policy. These methods are:

■ get_default_policies

■ get_validation_policies

■ set_default_policies

■ set_validation_policies

Page 117: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Policy-related Methods

Application Development with TME 10 ADE 4–3

Implem

entations forC

CM

S M

ethods

The IDL signatures of the two policy retrieval methods are shownbelow.

void get_default_policies( out Database::nmval_list def_attrs);

void get_validation_policies( out Database::nmval_list def_attrs);

The algorithms forget_default_policies andget_validation_policiesare nearly identical, differing only in which profile record they mustread. Both functions take the object reference of a profile and a recordkey and returns a copy of the record’s attributes.

As with many of the other functions and methods we have examined,the bulk ofget_default_policies andget_validation_policiesinvolves preparing to call and calling a method on the profileorganizer. In this case, the method isTMF_CCMS::Database::get_record.

The following listing shows the implementation forget_default_policies.1 void t_imp_TPL_PhoneListProfile_get_default_policies(

2 TPL_PhoneListProfile _TPL_PhoneListProfile,

3 Environment *_ev,

4 transaction _transaction,

5 TMF_CCMS_Database_nmval_list* def_attrs) {

6

7 char *db_name;

8 Object org;

9 TMF_CCMS_Database_record rec;

10 ml_t *mh = ml_create();

11

12 /* Get the database name, profile manager, etc. */

13 db_name = _t_imp_TPL_PhoneListProfile__get_db_name(

14 _TPL_PhoneListProfile,

15 _ev);

16 ml_attach_addr(mh, db_name);

17

18 profile_mgr =

19 _t_imp_TPL_PhoneListProfile__get_profile_organizer(

20 _TPL_PhoneListProfile,_ev);

Page 118: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Policy-related Methods

4–4 Version 3.6

21 ml_attach_Object_reference(mh, org);

22

23 key = get_def_rec_key(_TPL_PhoneListProfile);

24 ml_attach_addr(mh, key);

25

26 /* Get the default record */

27 Try {

28 t_TMF_CCMS_Database_get_record(profile_mgr, _ev,

29 Trans_sub, db_name, key,

30 FALSE, &rec);

31 }

32 Catch(ExEntryNotFound, ex) {

33 ExPhoneError *ex1 = (ExPhoneError *)

34 ExPhoneErrorNew(phone_msgs, no_pol_rec);

35 ContextThrow(ex1->type_name, ex1);

36 }

37 EndTry;

38

39 ml_attach_ORB_output(mh, &rec);

40

41 /* Make a copy of it to return */

42 *attrs = _t_copy_TMF_CCMS_Database_nmval_list(

43 _ev, &rec.attrs);

44

45 ml_destroy(mh);

46 }

When you make a copy of a complex data type like a sequence, youmust make sure that you make a “deep copy.” A deep copy not onlyduplicates the data structure, but also any memory referenced bypointers within the data structure. For example, annmval_listsequence is a list of structures that contain pointers. A regular copyduplicates the structures and their pointers, but the pointers in bothsequences reference the same memory. Although you can use this factto your advantage if you are careful, it can be a major problem whenpointer data is unwittingly shared. A deep copy, on the other hand,makes a duplicate of the referenced data. The result is a completelyindependent copy of the data.

When you run the IDL compiler, it generates a set of convenienceroutines for each user-defined data type. These convenience functionsinclude a routine that can make a deep copy of that data type. The

Page 119: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Policy-related Methods

Application Development with TME 10 ADE 4–5

Implem

entations forC

CM

S M

ethods

get_default_policies method uses the deep copy function generatedfor thenmval_list data type to make the return copy (line 42 above).

The implementation forget_validation_policies is very similar.1 void

t_imp_TPL_PhoneListProfile_get_validation_policies(

2 TPL_PhoneListProfile _TPL_PhoneListProfile,

3 Environment *_ev,

4 transaction _transaction,

5 TMF_CCMS_Database_nmval_list* val_attrs) {

6

7 char *key, *db_name;

8 Object profile_mgr;

9 TMF_CCMS_Database_record rec;

10 ml_t *mh = ml_create();

11

12 db_name = _t_imp_TPL_PhoneListProfile__get_db_name(

13 _TPL_PhoneListProfile,

14 _ev);

15

16 profile_mgr =_t_imp_TPL_PhoneListProfile__get_profile_organizer(

17 _TPL_PhoneListProfile,

18 _ev);

19 ml_attach_Object_reference(mh, profile_mgr);

20

21 key = get_val_rec_key(_TPL_PhoneListProfile);

22 ml_attach_addr(mh, key);

23

24 Try {

25t_TMF_CCMS_Database_get_record(profile_mgr,

26 _ev,

27 Trans_sub,

28 db_name,

29 key,

30 FALSE,

31 &rec);

32 }

33 Catch(ExEntryNotFound, ex) {

34 ExPhoneError *ex1 = (ExPhoneError*)ExPhoneErrorNew(phone_msgs,

35

Page 120: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Policy-related Methods

4–6 Version 3.6

36 no_val_rec);

37 ContextThrow(ex1->type_name, ex1);

38 }

39 EndTry;

40

41 ml_attach_ORB_output(mh, &rec);

42

43 *val_attrs = _t_copy_TMF_CCMS_Database_nmval_list(_ev,&rec.attrs);

44

45 ml_destroy(mh);

46 }

47

The operations for setting policies on a profile are very similar to thosethat retrieve policies. The IDL signatures of the two methods areshown below.

void set_default_policies( in Database::nmval_list def_attrs);

void set_validation_policies( in Database::nmval_list def_attrs);

The operations take a sequence of attributes and write them to theprofile’s default and validation records, respectively.

The Tivoli/Phone implementations of theset_default_policies andset_validation_policies methods are built around a common functioncalledset_profile_policy. Theset_profile_policy function takes thekey of either the validation or default policy record and updates therecord with the given sequence of attributes. The function uses theTMF_CCMS::Database::set_values method on the profile organizerobject to update the policy records.

The implementation forset_validation_policies is shown here.1 void

t_imp_TPL_PhoneListProfile_set_validation_policies(

2 TPL_PhoneListProfile _TPL_PhoneListProfile,

3 Environment *_ev,

4 transaction _transaction,

5 TMF_CCMS_Database_nmval_list* val_attrs)

6

7 {

8 char *db_name, *key;

Page 121: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Policy-related Methods

Application Development with TME 10 ADE 4–7

Implem

entations forC

CM

S M

ethods

9 Object profile_mgr;

10 ml_t *mh = ml_create();

11

12 /* Get the database name, profile manager, etc. */

13 db_name = _t_imp_TPL_PhoneListProfile__get_db_name(

14 _TPL_PhoneListProfile, _ev);

15 ml_attach_addr(mh, db_name);

16

17 profile_mgr =

18 _t_imp_TPL_PhoneListProfile__get_profile_organizer(

19 _TPL_PhoneListProfile, _ev);

20 ml_attach_Object_reference(mh, profile_mgr);

21

22 key = get_val_rec_key(_TPL_PhoneListProfile);

23 ml_attach_addr(mh, key);

24

25 /* Get the specified policy record */

26 Try {

27 t_TMF_CCMS_Database_set_values(profile_mgr, _ev,

28 Trans_sub, db_name, val_attrs,

29 key, FALSE);

30 }

31 Catch(ExEntryNotFound, ex) {

32 ExPhoneError *ex1 = (ExPhoneError *)

33 ExPhoneErrorNew(phone_msgs, no_val_rec);

34 ContextThrow(ex1->type_name, ex1);

35 }

36 EndTry;

37

38 ml_destroy(mh);

39 }

Theset_default_policies method is very similar. It differs only inwhich record it sets.1 void t_imp_TPL_PhoneListProfile_set_default_policies(

2 TPL_PhoneListProfile _TPL_PhoneListProfile,

3 Environment *_ev,

4 transaction _transaction,

5 TMF_CCMS_Database_nmval_list* def_attrs)

6 {

7

8 char *db_name, *key;

Page 122: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Policy-related Methods

4–8 Version 3.6

9 Object profile_mgr;

10 ml_t *mh = ml_create();

11

12 db_name = _t_imp_TPL_PhoneListProfile__get_db_name(

13 _TPL_PhoneListProfile,

14 _ev);

15 ml_attach_addr(mh, db_name);

16

17 profile_mgr =_t_imp_TPL_PhoneListProfile__get_profile_organizer(

18 _TPL_PhoneListProfile,

19 _ev);

20 ml_attach_Object_reference(mh, profile_mgr);

21

22 key = get_def_rec_key(_TPL_PhoneListProfile);

23 ml_attach_addr(mh, key);

24

25 Try {

26 t_TMF_CCMS_Database_set_values(profile_mgr,

27 _ev,

28 Trans_sub,

29 db_name,

30 key,

31 def_attrs,

32 FALSE);

33 }

34 Catch(ExEntryNotFound, ex) {

35 ExPhoneError *ex1 = (ExPhoneError*)ExPhoneErrorNew(phone_msgs,

36

37 no_def_rec);

38 ContextThrow(ex1->type_name, ex1);

39 }

40 EndTry;

41

42 ml_destroy(mh);

43 }

Page 123: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Policy-related Methods

Application Development with TME 10 ADE 4–9

Implem

entations forC

CM

S M

ethods

Enabling and Disabling ValidationCCMS determines whether it is to enforce validation policy on aprofile by checking theval_disabled flag on the profile’s validationrecord. When this flag is set, CCMS does not enforce validation policyon the profile’s records; when the flag is clear, policy is enforced.

Profile classes inherit two operations that allow a client to controlwhether validation policy is enforced on a profile. You must provideimplementations for both operations. The methods’ IDL signatures areshown below.

void disable_validation();void enable_validation();

Since bothenable_validation anddisable_validation toggle the samerecord flag (val_disabled), Tivoli/Phone implements them aswrappers to a single function calledset_validation_status. Thisfunction takes a boolean value and uses it to set the state of theval_disabled flag on the validation record.1 void set_validation_status(

2 TPL_PhoneListProfile o,

3 Environment *_ev,

4 tmf_boolean disable)

5 {

6 Object org;

7 char *db_name, *val_key;

8 TMF_CCMS_Database_record rec;

9 ml_t *mh = ml_create();

10 memset(&rec, 0, sizeof(TMF_CCMS_Database_record));

11

12 /*

13 * Get the profile’s profile organizer object

14 */

15 profile_org =

16 _t_imp_TPL_PhoneListProfile__get_profile_organizer

17 (o, _ev);

18 ml_attach_Object_reference(mh, profile_org);

19

20 db_name = _t_imp_TPL_PhoneListProfile__get_db_name

21 (o, _ev);

22 ml_attach_addr(mh, db_name);

Page 124: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Policy-related Methods

4–10 Version 3.6

23

24 val_key = get_val_rec_key(o);

25 ml_attach_addr(mh, val_key);

26 /*

27 * Set/clear the val_disabled flag on the

28 * validation record.

29 */

30 t_TMF_CCMS_Database_set_record_flags(

31 org, _ev, Trans_none,

32 db_name, val_key,

33 TMF_CCMS_Database_val_disabled,

34 disable);

35

36 ml_destroy(mh);

37 }

Theset_validation_status function gets the key of the validationrecord, the object reference of the profile organizer, and the name ofthe profile database. The function then calls theTMF_CCMS::Database::set_record_flags method on the profileorganizer to set the state of theval_disabled flag.

Since theset_validation_status function shoulders the work, theimplementations ofenable_validation anddisable_validation arevery simple.1 void t_imp_TPL_PhoneListProfile_disable_validation(

2 TPL_PhoneListProfile o,

3 Environment *_ev,

4 transaction _transaction)

5 {

6

7 set_validation_status(o, _ev, TRUE);

8 }

9

10 void t_imp_TPL_PhoneListProfile_enable_validation(

11 TPL_PhoneListProfile o,

12 Environment *_ev,

13 transaction _transaction)

14 {

15

16 set_validation_status(o, _ev, FALSE);

17 }

Page 125: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Policy-related Methods

Application Development with TME 10 ADE 4–11

Implem

entations forC

CM

S M

ethods

Profile applications also inherit an operation called_get_validation_enabled from TMF_CCMS::Profile . The IDLsignature of the method is shown below.

boolean _get_validation_enabled();

The Tivoli/Print implementation for_get_validation_enabledretrieves the profile’s validation policy record and examines therecord’sval_disabled flag. If the flag is clear, the method returnsTRUE; if the flag is set, the method returnsFALSE.1 tmf_boolean

2 t_imp_TPL_PhoneListProfile__get_validation_enabled(

3 TPL_PhoneListProfile o,

4 Environment *_ev,

5 transaction _transaction)

6 {

7 Object profile_org;

8 char *db_name, *val_key;

9 TMF_CCMS_Database_record rec;

10 ml_t *mh = ml_create();

11 tmf_boolean enabled;

12

13 memset(&rec, 0, sizeof(TMF_CCMS_Database_record));

14

15 /* Get the profile’s profile organizer object*/

16 profile_org =

17 _t_imp_TPL_PhoneListProfile__get_profile_organizer(

18 o, _ev);

19 ml_attach_Object_reference(mh, profile_org);

20

21 db_name =

22 _t_imp_TPL_PhoneListProfile__get_db_name(

23 o, _ev);

24 ml_attach_addr(mh, db_name);

25

26 /* Get the validation record key */

27 val_key = get_val_rec_key(o);

28 ml_attach_addr(mh, val_key);

29

30 t_TMF_CCMS_Database_get_record(profile_org, _ev,

31 Trans_revocable, db_name,

32 val_key, FALSE, &rec);

Page 126: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Policy-related Methods

4–12 Version 3.6

33

34 /* Set the return flag based on the val_disabled flag*/

35 enabled = (rec.flags & TMF_CCMS_Database_val_disabled)

36 ? FALSE : TRUE;

37

38 ml_destroy(mh);

39 return(enabled);

40 }

The implementation of_get_validation_enabled uses theTMF_CCMS::Database::get_record method to retrieve thevalidation record. Then it is a simple matter to check theval_disabledflag and return the appropriate value.

The validate OperationAlthough changes to a profile’s database are normally validated whenthe change is made, it is possible for a profile to contain records thatdo not meet policy criteria. For example, if you change a record whilevalidation is disabled, CCMS does not attempt to validate the changewhen this policy is re-enabled.

To solve this problem, theTMF_CCMS::Profile interface defines avalidate operation that checks a set of records in the profile’s databaseagainst the validation policies. The IDL signature ofvalidate is shownbelow.

void validate(in TMF_Types::StringList key_list, out TMF_CCMS::Database::record_list failed);

The method takes a sequence of record keys and returns a sequence ofrecords that did not meet the validation policy criteria.

As with the other policy-related methods inherited by your profileclass, you must provide an implementation for thevalidate method.Your implementation does not have to do the work of actuallyvalidating the records against the profile’s policies. Profile organizers

Parameter Description

key_list Sequence containing keys of the records to validate

failed Records that did not meet validation policy

Page 127: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Policy-related Methods

Application Development with TME 10 ADE 4–13

Implem

entations forC

CM

S M

ethods

support a method,TMF_CCMS::ProfileOrganizer::validate , whichperforms that job for you. Your implementation simply runs thevalidate method on the profile organizer to validate the records.

By now, the first part of the implementation for thevalidate methodshould look very familiar. The method gets the profile’s database nameand the object reference of the profile organizer so it can invoke theProfileOrganizer::validate method.1 void t_imp_TPL_PhoneListProfile_validate(

2 TPL_PhoneListProfile o,

3 Environment *ev,

4 transaction trans,

5 TMF_Types_StringList *key_list,

6 TMF_CCMS_Database_record_list *failed)

7 {

8 ml_t *mh = ml_create();

9 char *db_name;

10 Object org;

11 memset(failed, 0,

12 sizeof(TMF_CCMS_Database_record_list));

13

14 /*Get the profile organizer ref and the database name */

15 org =

16 _t_imp_TPL_PhoneListProfile__get_profile_organizer

17 (obj, _ev);

18 ml_attach_Object_reference(mh, org);

19

20 db_name = _t_imp_TPL_PhoneListProfile__get_db_name(

21 o, _ev);

22 ml_attach_addr(mh, db_name);

The method then calls thevalidate method on the profile organizer.The profile organizer’svalidate method handles the actualenforcement of policy on the records.23 /*

24 * Call the validate method on the profile organizer to

25 * perform the validation.

26 */

27 Try {

28 t_TMF_CCMS_ProfileOrganizer_validate(org, _ev,

29 Trans_sub, db_name,

30 key_list, failed);

Page 128: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Removing a Profile

4–14 Version 3.6

31 }

32 CatchAll() {

33 /* Ignore the exception, since it’s encoded in

34 * the failed list.

35 */

36 }

37 EndTry;

38

39 ml_destroy(mh);

40 }

TheProfileOrganizer::validate method returns a sequence of recordsthat did not meet the validation criteria. Your method implementationpasses this sequence of records back to the client that invoked themethod.

Removing a ProfileAnother fundamental operation that your profile class inherits fromTMF_CCMS::Profile is remove. Theremove operation deletes aprofile object and removes the records from its database.The IDLsignature of theremove method is shown below.

void remove();

TME 10 ADE provides a implementation for theremove operation.Tivoli/Phone overrides the standard implementation with one of itsown. To override an implementation, you simply list the operation inyour implementation specification (.imp file) and provide animplementation. You still have access to the implementation that youoverride through itsparent stub. Your implementation can perform itsspecial actions and then call the standard implementation. This allowsyou to extend the behavior of a method without having to duplicateexisting code.

Page 129: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Removing a Profile

Application Development with TME 10 ADE 4–15

Implem

entations forC

CM

S M

ethods

The Tivoli/Phone implementation ofremove performs the followingactions:

1. Ensures that the profile object can be deleted. Tivoli/Phonerequires that the profile being deleted be an “original.” That is, itcannot be a local copy of a profile that resides on a subscriber.

2. Calls the standard implementation of theremove method tohandle the actual removal of the profile object.

3. Logs a notice to the Tivoli/Phone notice group.

To determine whether the profile is the original or a subscriber’s copy,the method checks ther_local flag on the default policy record. If ther_local flag is set, the method throws anExPermission exception.1 void t_imp_TPL_PhoneListProfile_remove(

2 TPL_PhoneListProfile o,

3 Environment *ev,

4 transaction _transaction) {

5

6 ml_t *mh = ml_create();

7 Object profile_mgr;

8 TMF_CCMS_Database_record rec;

9 char *def_rec_key, *db_name, *profile_name;

10 TMF_CCMS_subscriber_list sublist;

11 any notice_any;

12 tmf_msg_t *msg;

13

14 ...

15 /* Check to see if we are in a "local" context. We

16 * can only remove a profile in the source context.

17 */

18 t_TMF_CCMS_Database_get_record(profile_mgr,

19 _ev, Trans_sub, db_name,

20 def_rec_key, FALSE, &rec);

21

22 if ((rec.flags & TMF_CCMS_Database_r_local) == 0) {

23 Throw(ExPermission_new(profile_name,

24 "remove"));

25 }

When you override a method implementation, the Tivoli IDL compilergenerates aparent stubthat allows you to invoke the overridden

Page 130: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Populating a Profile from a File

4–16 Version 3.6

implementation. The Tivoli/Phone remove implementation uses aparent stub to invoke the overridden TME 10 ADE implementation.The parentremove method removes the profile object from the TME10 database.26 /*

27 * Call the parent class’ delete method.

28 * The parent class takes care of actually

29 * deleting the profile object.

30 */

31 _t_p_imp_TPL_PhoneListProfile_remove(o,

32 _ev, Trans_sub);

When the parent method completes,remove logs an audit notice to theapplication’s notice group.33 /* Log an obituary notice */

34 memset(&notice_any, 0, sizeof(notice_any));

35 notice_any._type = TC_string;

36 notice_any._value = &profile_name;

37

38 msg = tmfMsgNew(phone_msgs,

39 remove_success_notice, notice_any);

40

41 tmf_msg_log(msg, NOTICE_GROUP, TMF_Notice_Notice);

42 tmf_msg_destroy(msg);

43

44 ml_destroy(mh);

45 }

Populating a Profile from a FileIt is often useful to create a profile object and then populate it withrecords using some outside source, such as a system file. For example,in a user management application you might create a profile and thenfill it with records using the/etc/passwd file as the source. TheTMF_CCMS::Profile interface defines an operation calledpopulateto support this kind of import behavior. The operation’s IDL signatureis shown below.

void populate( in TMF_CCMS::ProfileEndpoint source, in TMF_CCMS::Profile::populate_flag flag,

Page 131: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Populating a Profile from a File

Application Development with TME 10 ADE 4–17

Implem

entations forC

CM

S M

ethods

in TMF_Types::StringList key_list, out TMF_CCMS::Database::add_result_list results);

There is no standard implementation for the operation forpopulate,since its behavior is application-specific. The Tivoli/Phoneimplementation ofpopulate creates records based on the contents of acolon-delimited import file called/phone/phone.txt.

To parse the import file, the method invokes theplbo::discover_phonelist method on the endpoint where the fileresides. Thediscover_phonelist method reads the import file andreturns a sequence ofPhoneEntryInfo structures. You can find adiscussion of the implementation ofdiscover_phonelist in Chapter 6,“Profile Endpoint Methods.”1 void t_imp_TPL_PhoneListProfile_populate(

2 TPL_PhoneListProfile obj,

3 Environment *ev,

4 transaction trans,

5 TMF_CCMS_ProfileEndpoint source,

6 TMF_CCMS_Profile_populate_flag flag,

7 TMF_Types_StringList *key_list,

8 TMF_CCMS_Database_add_result_list *results)

9 {

10

11 TPL_PhoneEntryInfoList entries;

12 TPL_PhoneEntryInfo *entry;

13 ml_t *mh = ml_create();

14 TMF_Types_StringList old_keys;

15 Environment loc_ev = {0};

Parameter Description

source Object reference of the endpoint where the file resides

flag Flag that controls whether the import overwrites existingrecords

key_list Restricts population to entries whose keys match keys inthe sequence

results Sequence that contains information about records thatcould not be created

Page 132: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Populating a Profile from a File

4–18 Version 3.6

16 int num_old_keys, num_new_recs, num_failed;

17 int volatile i;

18 TMF_Types_StringList new_keys;

19 char *key;

20 void *vp;

21

22 seq_init((sequence_t *)&entries);

23 seq_init((sequence_t *)results);

24

25 /* Discover entries in the import file */

26 t_plbo_discover_phonelist(source, ev,

27 Trans_revocable,

28 PHONE_DATAFILE, &entries);

29 ml_attach_ORB_generic(mh, &entries,

30 TC_TPL_PhoneEntryInfoList);

Next, the method builds lists of keys to the newly discovered recordsand the records that are already in the profile. The method uses the keylists to search for collisions between the two sets of records.31 /* Sort the new entries by their keys */

32 num_new_recs = seq_len((sequence_t *)&entries);

33 qsort(seq_buffer(entries), num_new_recs,

34 sizeof(TPL_PhoneEntryInfo), cmp_phone_key);

35

36 /*

37 * Sort the entries by name and create

38 * a sequence of keys

39 */

40 seq_init((sequence_t *)&new_keys);

41 for (i = 0; i < num_new_recs; i++) {

42 entry = (TPL_PhoneEntryInfo *)

43 seq_get((sequence_t *)&entries, i,

44 sizeof(TPL_PhoneEntryInfo));

45

46 key = make_record_key(entry);

47 seq_add((sequence_t *)&new_keys, &key,

48 sizeof(char *));

49 }

50

51 /*

52 * Get a list of the keys for records currently

53 * in the target profile.

Page 133: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Populating a Profile from a File

Application Development with TME 10 ADE 4–19

Implem

entations forC

CM

S M

ethods

54 */

55 t_TPL_PhoneListProfile_list_phone_entries(

56 obj, &loc_ev, Trans_sub, &old_keys);

57

58 num_old_keys = seq_len((sequence_t *)&old_keys);

59

60 /* If the profile isn’t empty, sort the list of

61 * existing entries by key

62 */

63 if (num_old_keys > 0) {

64 qsort(seq_buffer(old_keys), num_old_keys,

65 sizeof(char *), cmp_str_seq);

66 }

After the method builds the lists of new and existing records keys, itbegins the process of populating the profile database. There are twomodes of population: overwrite and append. In the overwrite mode,populate removes all the records in the profile before creating the newrecords. Thispopulate implementation invokes thePhoneListProfile::delete_entries method and passes it the sequenceof existing keys.67

68 /*

69 * Populate has two modes: append and overwrite. If they

70 * want to overwrite the profile, just remove the

71 * existing records.

72 */

73 if (flag == TMF_CCMS_Profile_overwrite) {

74 /*

75 * Loop through the list of existing records and

76 * delete each one.

77 */

78 for (i = 0; i < num_old_keys; i++) {

79 char **del_key;

80

81 del_key = (char **)seq_get(

82 (sequence_t *)&old_keys, i, sizeof(char *));

83 t_TPL_PhoneListProfile_delete_phone_entry

84 (obj, &loc_ev,

85 Trans_sub,

86 *del_key);

87 }

Page 134: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Populating a Profile from a File

4–20 Version 3.6

88 }

Append mode is slightly more complicated than overwrite mode. Inappend mode,populate must compare the keys of the existing recordswith the keys of the new records. Where there are key collisions, themethod retains the existing record. The Tivoli/Phone implementationof populate searches the list of existing keys for each new key. If arecord with the new key already exists, the method removes thecorresponding entry from theentries sequence.89 else {

90 num_new_recs = seq_len((sequence_t *)&entries);

91 for (i = num_new_recs - 1; i >= 0; i--) {

92 char **key;

93

94 key = (char **)seq_get(

95 (sequence_t *)&new_keys, i,

96 sizeof(char *));

97 Try {

98

99 /* If the entry exists, remove it from

100 * the list of new entries. If the

101 * entry is new, seq_find_sorted

102 * throws an exception that we ignore */

103 seq_find_sorted((sequence_t *) &old_keys,

104 seq_find_sorted((sequence_t *) &old_keys, key,

105 sizeof(*key), seq_strcmp);

106

107 entry = seq_remove(

108 (sequence_t *)&entries, i,

109 sizeof(TPL_PhoneEntryInfo));

110

111 tmf_free_generic(entry,

112 TC_TPL_PhoneEntryInfo);

113 mg_free(entry);

114

115 vp = seq_remove((sequence_t *) &new_keys,

116 i, sizeof(char *));

117 mg_free(vp);

118

119 num_new_recs--;

120

121 } Catch(ExNotFound, ex) {

Page 135: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Moving and Copying Records

Application Development with TME 10 ADE 4–21

Implem

entations forC

CM

S M

ethods

122 /* Ignore the exception, since it

123 * just means the new key wasn’t

124 * found in the existing list */

125 }

126 EndTry;

127 }

128 }

Finally, populate is ready to create the new entries. The method usestheTPL::PhoneListProfile::create_entries method to create all thenew records at once.129 /* Create the entries */

130 t_TPL_PhoneListProfile_create_entries(

131 obj, ev, Trans_sub,

132 &entries, results);

133

134 /* Free the memory for the sequences */

135 tmf_free_generic(&entries, TC_TPL_PhoneEntryInfoList);

136 num_failed = seq_len((sequence_t *)results);

137 ml_destroy(mh);

138 }

Moving and Copying RecordsTheTMF_CCMS::Profile interface defines themove_records andcopy_records methods for moving and copying records betweenprofiles. There are no default implementations for these methods, soyou must implement them if you want to support the move and copyoperations. Keep in mind that this information applies to the serverside of the application.

Themove_records method removes the specified set of records froma source profile and adds them to the target profile. Thecopy_recordsmethod copies records from a source profile and adds them to thetarget profile. The source profile is not affected by the copy operation.The IDL signatures ofcopy_records andmove_records are shownbelow.

void copy_records(in TMF_Types::StringList key_list, in TMF_CCMS::Profile source);

Page 136: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Moving and Copying Records

4–22 Version 3.6

void move_records(in TMF_Types::StringList key_list, in TMF_CCMS::Profile source);

Both methods are invoked on the target (destination) profile object.The methods take the object reference of the source profile and a listof keys for the records to move or copy.

If you have already implemented the basic record manipulationmethods for your profile, implementing thecopy_records andmove_records methods is easy. The Tivoli/Phone implementation ofcopy_records usesPhoneListProfile::get_phone_entries on thesource profile object to get the specified records. The method then runsTPL::PhoneListProfile::create_phone_entries to create the recordsin the target’s database.1 void t_imp_TPL_PhoneListProfile_copy_records(

2 TPL_PhoneListProfile target,

3 Environment *_ev,

4 transaction _transaction,

5 TMF_Types_StringList *key_list,

6 TMF_CCMS_Profile source)

7 {

8

9 TPL_PhoneEntryInfoList entries;

10 TMF_CCMS_Database_add_result_list results;

11

12 seq_init((sequence_t *)&entries);

13 seq_init((sequence_t *)&results);

14

15 /* Get the specified entries from the source profile */

16 Try {

17 t_TPL_PhoneListProfile_get_phone_entries(

18 source, _ev, Trans_sub,

19 key_list, &entries);

20

21 /* Create them in the destination profile */

Parameter Description

key_list Sequence of keys for records to move/copy

source Object reference of the profile where the records reside

Page 137: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Moving and Copying Records

Application Development with TME 10 ADE 4–23

Implem

entations forC

CM

S M

ethods

22 t_TPL_PhoneListProfile_create_entries(

23 target, _ev, Trans_sub,

24 &entries, &results);

25 }

26 Catch(ExException, ex) {

27 Rethrow;

28 }

29 EndTry;

If create_phone_entries returns anything in theresults outputparameter, there was an error creating one or more of the new records.In Tivoli/Phone’s implementation ofcopy_records, the copyoperation is an all-or-none affair; if one or more records cannot becopied, none of them are. The method checks theresults sequence andthrows an exception if it is not empty. The exception causes the copytransaction to abort, backing out the records that were copied.30 /*

31 * If there were any failures, throw an exception.

32 */

33 if (seq_len((sequence_t *)&results) > 0) {

34 any data;

35 ExPhoneData *ex;

36

37 data._type = TC_TMF_CCMS_Database_add_result_list;

38 data._value = &results;

39 ex = (ExPhoneData *)ExPhoneDataNew(phone_msgs,

40 move_failed,

41 &data);

42

43 Throw(ex->type_name, ex);

44 }

45 }

The implementation for themove_records method is nearly identicalto that ofcopy_records, exceptmove_records must also delete therecords from the source profile.1 void t_imp_TPL_PhoneListProfile_move_records(

2 TPL_PhoneListProfile target,

3 Environment *_ev,

4 transaction _transaction,

5 TMF_Types_StringList *key_list,

6 TMF_CCMS_Profile source)

Page 138: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Moving and Copying Records

4–24 Version 3.6

7 {

8

9 TPL_PhoneEntryInfoList entries;

10 TMF_CCMS_Database_add_result_list results;

11

12 seq_init((sequence_t *)&entries);

13 seq_init((sequence_t *)&results);

14

15 /* Get the specified entries from the source profile */

16 Try {

17 t_TPL_PhoneListProfile_get_phone_entries(

18 source, _ev, Trans_sub,

19 key_list, &entries);

20

21 /* Create them in the target profile */

22 t_TPL_PhoneListProfile_create_entries(

23 target, _ev, Trans_sub,

24 &entries, &results);

25

26 /* Remove records from the source profile */

27 if (seq_len((sequence_t *)&results) == 0) {

28 t_TPL_PhoneListProfile_delete_phone_entries(

29 source, _ev,

30 Trans_sub, key_list);

31 }

32 }

33 Catch(ExException, ex) {

34 ExPhoneError *ex1 = (ExPhoneError *)

35 ExPhoneErrorNew(phone_msgs,

36 move_failed_fatal);

37 ContextThrow(ex->type_name, ex1);

38 }

39 EndTry;

40

41 /*

42 * Report any errors.

43 */

44 if (seq_len((sequence_t *)&results) > 0) {

45 any data;

46 ExPhoneData *ex;

47

48 data._type = TC_TMF_CCMS_Database_add_result_list;

Page 139: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Moving and Copying Records

Application Development with TME 10 ADE 4–25

Implem

entations forC

CM

S M

ethods

49 data._value = &results;

50 ex = (ExPhoneData *)ExPhoneDataNew(phone_msgs,

51 move_failed,

52 &data);

53

54 Throw(ex->type_name, ex);

55 }

56 }

Page 140: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Moving and Copying Records

4–26 Version 3.6

Page 141: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Development with TME 10 ADE 5–1

Creating S

calableO

perations

5Creating Scalable Operations

In a distributed object environment, passing parameters and returningdata is not the same as it is when calling a function in a regularprogram. The Object Request Broker (ORB) must encode methodparameters and transmit them to wherever the target object resides.If a method returns data, the ORB must also encode the return data andpass it back to the client.

For each 100-byte record passed between the client and server,approximately 500 bytes of total memory are used. The client has acopy of the record, which it passes to the client stub. The client stubcopies the record and encodes it for transmission, which enlarges it to

5

Server(100 bytes)

ClientStub

ServerSkeleton

EncodedRecord(150 bytes)

150 bytes

EncodedRecord(150 bytes)

Client(100 bytes)

Page 142: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Input Data with IOM

5–2 Version 3.6

approximately 150 bytes. The stub transmits the encoded record to theserver skeleton which decodes the record and passes it to the serverimplementation. Passing a sequence of 5,000 records to the serverwould require 2.5MB of memory (1.25MB on the client and servereach) and would push 750Kb of data across the network.

You can create parameter scalability within an application in twoways. On the input side, you can prevent the client from passing largeamounts of data to a method as a parameter. Either require the client toinvoke the method in several stages or establish a directmethod-to-method connection through the inter-object message (IOM)service.

On the output side, you can use a mechanism callediteration to returndata in a scalable way. An iterator-based method returns only the firstn elements of a large sequence. It also returns an iterator handle, whichthe client can use to get subsequent chunks of the sequence. Iteratorsallow a client to process manageable chunks of data.

Scalable Input Data with IOMAn IOM channel is a direct socket connection between a client and aserver. The IOM service is a good way to ensure the scalability of inputdata, because the amount of data passed at one time between the clientand the server can be controlled at both ends of the channel. Instead ofpassing a large number of records to a method server, the client canestablish an IOM connection with the server and pass records directlyto the server implementation.

Using IOM to pass large amounts of data can improve performance,since the IOM channel bypasses the ORB in favor of a direct,method-to-method connection. IOM channels are secure, even thoughthe channel bypasses the ORB. Because the client establishes aconnection with a method by passing a unique key through the ORB,the ORB authenticates the receiver method at the time of invocation.

IOM Channels and ThreadsIOM channels and threads apply to the server, but not to LCF endpoints.This discussion is valid only for servers.

Page 143: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Input Data with IOM

Application Development with TME 10 ADE 5–3

Creating S

calableO

perations

When a client must establish an IOM connection with another method,it first creates an IOM key. Then, it must invoke the receivermethod—passing it the IOM key—and open its end of the IOMchannel. Here a problem arises: when one side opens its end of thechannel, execution is blocked until the other side opens its end. This isa problem in a single-threaded method, since the method cannot bothopen its end and invoke the receiver method. No matter which it doesfirst (open its end or invoke the receiver end), execution will blockforever, waiting for the other side to open its end of the channel.

The answer to this dilemma is to use multiple threads: one thread toopen the source method’s end of the channel and one thread to invokethe receiver method.

1. The method (main thread) creates the key to the IOM channel.

2. The main thread spawns a second thread whose sole job is toinvoke the receiver method (in this case

create_entries Methodmain

thread

1

25

6

keyreceiverthread

11

ORB

Key

3

Database::add_records

Key

4

8record

910

profiledatabase

12

IOM Channel

7

Page 144: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Input Data with IOM

5–4 Version 3.6

Database::add_records). The main thread passes the key to thereceiver thread so that it can pass it to the receiver method.

3. The receiver thread invokes theadd_records method and passesthe key to the ORB.

4. The ORB passes the key to theadd_records method.

5. Theadd_records method uses the IOM key to open its end of theIOM channel.

6. The main thread opens its end of the IOM channel and waits forthe receiver method to open its end. This step happensconcurrently with steps 3, 4, and 5.

7. The main thread loops, transmitting records over the IOMchannel.

8. Theadd_records method receives the records and writes them tothe profile database.

9. When the main thread has transmitted all records,add_recordsexits.

10. The thread that invokedadd_records terminates.

11. The receiver thread rejoins the main thread, which has beenblocked, waiting for the receiver thread to terminate.

12. Execution of the method continues on the main thread at the pointwhere the receiver thread rejoins the main thread.

Tivoli/Phone implements a method calledcreate_entries thatillustrates how to use multiple threads and the IOM service. Thecreate_entries method creates multiple address entries at once. TheIDL signature ofcreate_entries is shown below.

void create_entries( TPL::PhoneEntryInfoList entries, TMF_CCMS::Database::add_result_list *results)

Parameter Description

entries A sequence of entries to add to the profile

results A list of entries that could not be added (output)

Page 145: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Input Data with IOM

Application Development with TME 10 ADE 5–5

Creating S

calableO

perations

The implementation for this method uses theTMF_CCMS::Database::add_records method to create the recordsin the profile database. Since the number of records thatadd_recordscan create at once is theoretically unlimited, the method does notaccept the records as a parameter. The client (create_entries in thiscase) transmits the records toadd_records through an IOM channel.

To get started, the implementation ofcreate_entries sets up a profilerecord that it uses as the template for all the new records. Since all thenew records share the same basic record information (flags, policyrecord keys, and so on), the method uses the same structure toconstruct each new record. The method simply changes the record keyand list of attributes before transmitting each record toadd_records.1 void t_imp_TPL_PhoneListProfile_create_entries(

2 TPL_PhoneListProfile o,

3 Environment *_ev,

4 transaction _transaction,

5 TPL_PhoneEntryInfoList *entries,

6 TMF_CCMS_Database_add_result_list *results)

7 {

8 TMF_CCMS_Database_record_item rec;

9 SysAdminTypes_ObjectLabel obj_label;

10 TPL_PhoneEntryInfo *entry;

11 int i;

12 iom_handle_t *iom_hndl;

13 ml_t *mh = ml_create();

14 int volatile num_entries = 0, i;

15 pthread_t thread;

16 pthread_addr_t thread_status;

17 XSN_BUF *ebuf;

18 any arg, arg2;

19 TMF_Types_StringList notice_data;

20 tmf_msg_t *msg;

21 char *profile_name;

22

23 /* Initialize the record wrapper structure */

24 memset(&rec, 0,

25 sizeof(TMF_CCMS_Database_record_item));

26 rec.member_obj.objref = OBJECT_NIL;

27 rec.member_obj.label = "";

28 rec.source.objref = OBJECT_NIL;

Page 146: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Input Data with IOM

5–6 Version 3.6

29 rec.source.label = "";

30

31 /*

32 * Initialize the fields that will be

33 * the same for all new records.

34 */

35 rec.rec.pm_classname =

36 rec.rec.pe_classname = TMF_CCMS_Database_no_class;

37 rec.rec.flags = 0;

38 rec.rec.parent = get_def_rec_key(o);

39 ml_attach_addr(mh, rec.rec.parent);

40 rec.rec.validation = get_val_rec_key(o);

41 ml_attach_addr(mh, rec.rec.validation);

42 rec.rec.partition = get_partition_name(o);

43 ml_attach_addr(mh, rec.rec.partition);

44

45 obj_label.label = "";

46 obj_label.objref = OBJECT_NIL;

Now the method is ready to spawn the second “receiver” thread toinvoke the CCMSadd_records method and establish an IOMconnection with it. To do this, it calls the functionopen_connection.We will look at this function in detail in the next section.47 iom_hndl = open_connection(&thread, o,

48 entries, results);

After open_connection has spawned the receiver thread andestablished the IOM channel, it returns the channel’s handle to thecreate_entries method. The method can then begin sending CCMSrecords to theadd_records method over the channel.49 Try {

50

51 /*

52 * Go through all the entries, convert each

53 * to a CCMS nmval list and ship it out

54 * over the IOM channel.

55 */

56 num_entries = seq_len((sequence_t *)entries);

57 for (i = 0; i < num_entries; i++) {

58 entry = (TPL_PhoneEntryInfo *)

59 seq_get((sequence_t *)entries, i,

60 sizeof(TPL_PhoneEntryInfo));

Page 147: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Input Data with IOM

Application Development with TME 10 ADE 5–7

Creating S

calableO

perations

61 entry->flags = PP_ALL_FIELDS;

62

63 rec.key = make_record_key(entry);

64 rec.rec.flags = 0;

65

66 /* Convert the entry to an nmval */

67 seq_init((sequence_t *)&rec.rec.attrs);

68 convert_entry_to_nmval(entry,

69 &rec.rec.attrs);

70 if (entry->read_only == TRUE)

71 {rec.rec.flags |= TMF_CCMS_Database_r_readonly;

72 }

73 if (entry->fixed == TRUE)

74 {rec.rec.flags |= TMF_CCMS_Database_r_fixed;

75 }

76

77 /* Encode the data and send it */

78 ebuf = TypeCode_init_encode(TypeCode_ADR);

79 t_TypeCode_encode(

80 TC_TMF_CCMS_Database_record_item,

81 &rec, ebuf);

82

83 iom_send(iom_hndl, TypeCode_buffer(ebuf),

84 TypeCode_buf_length(ebuf));

85

86 TypeCode_free_buf(ebuf);

87

88 mg_free(rec.key);

89

90 }

91

92 CatchAll() {

93 ExPhoneError *ex =

94 (ExPhoneError *)ExPhoneErrorNew(

95 phone_msgs,

96 comm_error);

97 iom_close_input(iom_hndl);

98 iom_close(iom_hndl);

99 Throw(ex->type_name, ex);

100 }

101 EndTry;

Page 148: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Input Data with IOM

5–8 Version 3.6

When you send complex data types over an IOM channel, you must“flatten” the structure into a stream of bytes that can be transmittedover the wire. On the other end of the channel, the receiver mustreconstruct the data stream into its original structured form. In theexcerpt above, the method callst_TypeCode_encode to encode eachprofile record as a byte stream before callingiom_send to transmit it.

t_TypeCode_encode(TC_TMF_CCMS_Database_record_item, &rec, ebuf);

iom_send(iom_hndl, TypeCode_buffer(ebuf), TypeCode_buf_length(ebuf));

The first parameter oft_TypeCode_encode is the type code of the datastructure being encoded. The function uses the data marshallinginformation for the data type to encode the data. In theadd_recordsmethod (the receiver side), the encoded data is decoded usingt_TypeCode_decode. Again, the function uses the data type’smarshalling information to transform the stream of bytes into a CCMSrecord structure.

After thecreate_phone_entries method sends all its records, it closesthe IOM channel and waits for the receiver thread to terminate. Thereceiver thread terminates when theadd_records method finisheswriting the new records to the profile database.102 iom_close_input(iom_hndl);

103 iom_close(iom_hndl);

104

105 /* Wait for the other thread to complete */

106 pthread_join(thread, &thread_status);

To close the IOM channel gracefully,create_phone_entries first callsiom_close_input to signal that it is finished sending data and that it isclosing the channel. Thepthread_join call causes the method to blockuntil the receiver thread has terminated.

All that remains after the receiver thread has terminated is to log anotice recording the new entries. Thecreate_phone_entries methoduses the same technique of logging an aggregate message used by thereal_delete function (see Chapter 3, “Method Implementations”).107 /* Create a for the header of the notice */

108 memset(&arg, 0, sizeof(arg));

109 seq_init((sequence_t *)&notice_data);

Page 149: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Input Data with IOM

Application Development with TME 10 ADE 5–9

Creating S

calableO

perations

110 arg._type = TC_string;

111 seq_add((sequence_t *)&notice_data, &profile_name,

112 sizeof(char *));

113 arg._value = &profile_name;

114 msg = tmfMsgNew(phone_msgs,

115 add_header_notice, arg);

116

117 /*

118 * Create a second, nested message for the

119 * list of new records.

120 */

121 memset(&arg2, 0, sizeof(arg2));

122 seq_init((sequence_t *)&notice_data2);

123

124 for (i = 0; i < num_entries; i++) {

125 entry =

126 (TPL_PhoneEntryInfo *)seq_get(

127 (sequence_t *)entries, i,

128 sizeof(TPL_PhoneEntryInfo));

129

130 seq_add((sequence_t *)&notice_data2,

131 &entry->name, sizeof(char *));

132 }

133

134 /* Add the body message to the header message */

135 arg2._type = TC_TMF_Types_StringList;

136 arg2._value = &notice_data2;

137 tmfMsgAdd(msg, phone_msgs,

138 key_list, arg2, 1);

139

140 /* Log the notice */

141 tmf_msg_log(msg, NOTICE_GROUP, TMF_Notice_Notice);

142 tmf_msg_destroy(msg);

143

144 seq_free_buffer((sequence_t *)&notice_data);

145 seq_free_buffer((sequence_t *)&notice_data2);fs

146

147 ml_destroy(mh);

148 }

Page 150: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Input Data with IOM

5–10 Version 3.6

Starting the Receiver ThreadA very important piece of the implementation of thecreate_phone_entries method is the function calledopen_connection. This function spawns the second receiver thread onwhich the CCMSadd_records method runs and opens an IOMchannel to theadd_records method. When you spawn a new thread,you must specify two things:

■ The name of a function that runs when the new thread is started

■ An argument that is passed to the function that runs on the newthread

In the case ofcreate_phone_entries, the function that runs on thesecond thread is calledobjcall_add_records. The sole job of thisfunction is to invoke theadd_records method on the profile organizer.How doesobjcall_add_records get the information it needs to invoketheadd_records method? It gets the information through theargument passed to it by theopen_connection function.

The Tivoli/Phone application defines a data type calledthread_data_tthat it uses to pass data between the two threads. The definition of thestructure is shown below.

typedef struct { TMF_Types_OctetList iom_key; Object profile_org; char *db_name; TMF_CCMS_Database_add_result_list *results;} thread_data_t;

The thread_data_t structure contains all the information thatobjcall_add_records needs to invoke theadd_records method on theprofile organizer. Theopen_connection function initializes the fieldsof thethread_data_t structure before spawning the new thread.1 static iom_handle_t *open_connection(

2 pthread_t *thread,

3 TPL_PhoneListProfile o,

4 TMF_CCMS_Database_add_result_list *results)

5 {

6 thread_data_t *tcr;

7 Environment ev = {0};

8 iom_key_t *key;

Page 151: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Input Data with IOM

Application Development with TME 10 ADE 5–11

Creating S

calableO

perations

9 struct timeval tv;

10 iom_handle_t * volatile handle;

11

12 /* Set up out inter-thread communication record */

13 tcr = (thread_data_t *)mg_malloc(

14 sizeof(thread_data_t));

15 tcr->profile_org =

16 _t_imp_TPL_PhoneListProfile__get_profile_organizer(

17 o, &ev);

18 tcr->db_name =

19 _t_imp_TPL_PhoneListProfile__get_db_name(

20 o, &ev);

21 tcr->results = results;

22

23 /*

24 * Create an IOM key and stuff it into an

25 * octet list so it can be passed to the

26 * CCMS add_records operation.

27 */

28 key = iom_create();

29

30 tcr->iom_key._length = tcr->iom_key._maximum =

31 iom_key_size(key);

32 tcr->iom_key._buffer = key;

Next, the function spawns a thread usingtmf_thread_create. Thetmf_thread_create function spawns a thread and invokes thespecified routine (objcall_add_records) on the new thread. Thefunction also passes thethread_data_t structure (tcr) to the newthread.33 /*

34 * Spawn a new thread to open the receiver

35 * end of the channel.

36 * The objcall_add_records function is

37 * invoked by the thread to call add_records.

38 */

39 if (tmf_thread_create(

40 thread,

41 PTHREAD_ATTR_DEFAULT,

42 (thread_startroutine_t)objcall_add_records,

43 tcr) == -1) {

44 mg_free(key);

Page 152: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Input Data with IOM

5–12 Version 3.6

45 free_tcr(tcr);

46 Throw(ExSystem_new("Out of threads"));

47 }

After invoking the receiver thread, the function attempts to open thechannel. If the thread spawns correctly, the receiver thread opens theother end of the channel. Theopen_connection function returns theIOM handle to the caller.48 Try {

49 tv.tv_sec = 2*60;

50 tv.tv_usec = 0;

51 handle = iom_timed_open(key, &tv);

52 }

53 CatchAll() {

54 ExPhoneError *ex =

55 (ExPhoneError *)ExPhoneErrorNew(

56 phone_msgs,

57 comm_error);

58 iom_destroy(key);

59 Throw(ex->type_name, ex);

60 }

61 EndTry;

62

63 iom_destroy(key);

64

65 /* Return the IOM handle to the caller */

66 return(handle);

67 }

Theobjcall_add_records function is run when the receiver threadstarts. This function runs theadd_records method on the profileorganizer object. All the dataobjcall_add_records needs to invokethe method (the object reference of the profile organizer, IOM channelkey, and so on) is included in thepthread_data_t structure that ispassed to it.1 static void objcall_add_records(thread_data_t *tcr)

2 {

3 Environment ev = {0};

4

5 t_TMF_CCMS_Database_add_records(

6 tcr->profile_org, &ev, Trans_revocable,

7 tcr->db_name, &tcr->iom_key,

Page 153: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Output Data with Iterators

Application Development with TME 10 ADE 5–13

Creating S

calableO

perations

8 tcr->results);

9

10 /*

11 * Free the thread_data_t structure

12 * and terminate this thread.

13 */

14 free_tcr(tcr);

15 tmf_thread_exit(&ev);

16 }

When theadd_records method successfully completes, theobjcall_add_records function terminates the thread on which it isrunning. Whenobjcall_add_records callstmf_thread_exit toterminate the thread, the main thread unblocks and continuesexecution.

Scalable Output Data with IteratorsTME 10 ADE applications scale their output data using a mechanismcalled iteration. An iterator-based method returns data to a client on aclient-demand basis. The client requests a chunk of data, processes it,and releases it before fetching the next chunk. From a client’sperspective, an iterator-based method works in the following way:

1. A client calls a method that returns a large amount of data. Theserver returns as many elements as it can (determined by theserver). If there is more data than can be transmitted at once, theserver returns a portion of the data and an iterator handle.

2. The client processes the returned data and releases it.

3. The client uses the iterator handle to get the next chunk of data.The process of fetching a chunk of data, processing it, andreleasing it continues until the client has received all the data.

4. When the client receives the last block of data, the iterator serverdestroys the temporary iterator handle. If the client finishes withthe data before it has obtained all the elements, it must manuallydestroy the iterator handle.

The code excerpt below from the Tivoli/Phone application shows howa client might use an iterator-based method. Note that the iterator codeis on the server side, not the endpoint side.

Page 154: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Output Data with Iterators

5–14 Version 3.6

1 void find_default_profile(void)

2 {

3 ...

4 /* Fetch the members of the collection */

5 t_SysAdmin_FilteredCollection_find_members(

6 class,&ev, Trans_revocable,

7 &interface_list,

8 DEF_PHONE_PROFILE_NAME,

9 50, &out_list, &iterator);

10

11 len = seq_len((sequence_t *)&out_list);

12 for (i = 0; i < len; i++ ) {

13 /* Process the first batch */

14 }

15

16 ORBfree(&out_list);

17

18 /* If find_memebers returned an iterator,

19 * fetch successive blocks and process */

20 more = !Object_is_nil(iterator, &ev);

21 while (more) {

22

23 more = t_SysAdmin_MemberLabelIterator_next_n(

24 iterator, &ev, Trans_revocable,

25 50, &out_list);

26

27 len = seq_len((sequence_t *)&out_list);

28 for (i = 0; i < len; i++ ) {

29 /* Process the next batch */

30 }

31 ORBfree(&out_list);

32 }

33 }

The client calls thefind_members method to get the first chunk ofmembers from a collection. It processes the members in the chunk andthen frees them. If there are more elements to be returned (iterator isnotOBJECT_NIL ), the client uses thenext_n method to get the nextchunk. The client processes and frees each chunk before fetching thenext chunk. Whennext_n returnsFALSE, the client is finishedfetching all the elements.

Page 155: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Output Data with Iterators

Application Development with TME 10 ADE 5–15

Creating S

calableO

perations

Implementing an Iterator-based MethodThe interaction between a client and an iterator-based method is fairlystraightforward. However, the implementation of an iterator-basedmethod is slightly more complicated. The method server must be ableto service several iterator requests at a time and must be able to savestate information between method calls.

When a client invokes a method that can return an iterator, the serverallocates an iterator state structure. Tivoli/Phone maintains all theinformation that an iterator might need to fetch records from theprofile. This includes:

■ The object reference of the profile organizer

■ The name of the profile database

■ The partition name

■ The key of the last record returned

The server then marshals the nextn records from the profile. Thenumber of elements that a method can return in one block isdetermined by the application. Although returning 1,000 100-byterecords at once is not a good idea, neither is returning only a few at atime. Choose a block size that balances the cost in network bandwidthwith the performance cost of extra method calls required to fetch eachchunk of data.

If the client requested more thann records, the server returnsn recordsand an iterator handle that the client can use to fetch the remainingrecords. Tivoli/Phone stores the iterator handle as a sub-object ID ofthe profile’s object reference. The CORBA specification defines thesub-object ID as an optional part of an object reference. Theinterpretation of a sub-object ID is left to each application.

Tivoli/Phone uses a daemon-style server so that state informationabout the iterator can persist between method calls. The daemon serveralso allows a single process to handle multiple iterator requestssimultaneously. The state information for each iterator is stored in alist, keyed by the iterator handle. When a client calls the method to getthe next chunk of records, the server pulls the iterator handle from theobject’s sub-object ID and locates the state information.

Page 156: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Output Data with Iterators

5–16 Version 3.6

The following diagram illustrates the iteration mechanism.

1. Client invokes aget_all method.

2. The method marshals the first chunk of records and saves stateinformation about the iterator.

3. The client receives the first chunk of records and an iteratorhandle.

4. The client invokes anext_chunk method, passing it the iteratorhandle.

5. The method uses the iterator handle to locate the iterator’s stateinformation.

6. The client receives the next chunk of records.

ThePhoneListProfile interface of the Tivoli/Phone applicationdefines two methods that can return iterators to their callers:get_all_entries andfind_by_name. Both methods can potentiallyreturn large numbers of records, so the application uses an iterator

Client

get_all next_chunk

Daemon Server

1 3

2

4 6

5state

information

profiledatabase

Page 157: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Output Data with Iterators

Application Development with TME 10 ADE 5–17

Creating S

calableO

perations

interface to control how many records are returned at one time. TheIDL signatures of the operations are shown below.

void get_all_entries( out PhoneEntryInfoList entries, out PhoneListIterator iterator);

void find_by_name( in string name, out PhoneEntryInfoList entries, out PhoneListIterator iterator);

ThePhoneListProfile class also supports two methods that processthe iterators returned byget_all_entries andfind_by_name. Thesemethods, which are defined by thePhoneListIterator interface, arecallednext_entries anddestroy_iterator.1 interface PhoneListIterator {

2 boolean next_entries(

3 in long how_many,

4 out PhoneEntryInfoList entry_list)

5 raises(SysAdminException::ExInvalid);

6

7 void destroy_iterator();

8 }

Parameter Description

entries Sequence of profile entries

iterator Reference of the target object encoded with aniterator handle

Parameter Description

name Search string to match

entries Sequence of profile entries

iterator Reference of the target object encoded with aniterator handle

Page 158: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Output Data with Iterators

5–18 Version 3.6

Thenext_entries operation returns the next batch of records given avalid iterator. Thedestroy_iterator operation allows a client torelease an iterator before the iterator has returned all of the records.

Tivoli/Phone implements its iterator-based methods as a single,threaded daemon server. The daemon server is required because theapplication must maintain state information about the iterator betweeneach call. The program definition of the Tivoli/Phone iterator server isshown below.1 program Phone_prog2 timeout = 180 for

2 imp_TPL::PhoneListProfile {

3 executes {

4 list_phone_entries,

5 get_all_entries,

6 find_by_name,

7 next_entries,

8 destroy_iterator

9 } threaded daemon;

10

11 startup {

12 "tas_init",

13 "query_init"

14 };

15 };

The daemon server defined above encapsulates all the iterator-basedoperations in a single server. The server is set to time out after 180seconds. This is theoretically a problem, because it is possible thatthere might be significant delays between calls to an iterator method.In practice, however, all the clients of the Tivoli/Phone iterators willcomplete their task well before the time limit.

Implementation: Initial MethodTo illustrate how an iterator-based method is implemented, we willlook at theget_all_entries method. This method returns the first blockof 50 entries from a Tivoli/Phone profile object. If there are more than50 entries,get_all_entries also returns an iterator handle. The clientcan use the iterator handle with thenext_entries method to getsubsequent chunks of 50 records.

Page 159: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Output Data with Iterators

Application Development with TME 10 ADE 5–19

Creating S

calableO

perations

The method first calls a function (create_phone_iterator) to create aniterator state structure. The function returns a unique handle for thestructure. The method then calls theiterator_copy function to fetchthe first block of records.1 void t_imp_TPL_PhoneListProfile_get_all_entries(

2 TPL_PhoneListProfile o,

3 Environment *_ev,

4 transaction _transaction,

5 TPL_PhoneEntryInfoList *entries,

6 TPL_PhoneListIterator *iterator)

7 {

8 SubObjectId it_ref;

9 char *db_name, *partition;

10 Object prof_org;

11 ml_t *mh = ml_create();

12 tmf_boolean more;

13

14 ...

15

16 /*

17 * Create a temporary iterator structure and

18 * get the first chunk of entries.

19 */

20 it_ref = create_phone_iterator(_ev, db_name,

21 partition, NULL, prof_org);

22

23 more = iterator_copy(it_ref, _ev,

24 entries, ITERATOR_MAX);

25

26 /* If there are more records, create an

27 * object reference that contains the

28 * iterator handle.

29 if (more) {

30 *iterator = BOA_create_subobject(

31 tmf_locate_boa(), _ev,

32 obj, it_ref);

33 }

34 else {

35 *iterator = OBJECT_NIL;

36 }

37 }

Page 160: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Output Data with Iterators

5–20 Version 3.6

The iterator_copy function returns a flag that indicates whether thereare more records to be returned. If there are additional records, themethod encodes the key to the state information structure as asub-object ID of the invoking object.

Implementation: Iterator Service MethodThe Tivoli/Phone application defines a method callednext_entriesthat allows a client to fetch blocks of records after a call toget_all_entries orfind_by_name. Thenext_entries method takes theiterator handle returned byget_all_entries andfind_by_name.

Thenext_entries method allows you to specify the number of recordsto return. This is useful if a client needs a greater level of control overthe size of the block. The Tivoli/Phone implementation enforces animplicit limit of 50 records to prevent a client from accidentlyrequesting too many records at once.1 tmf_boolean t_imp_TPL_PhoneListProfile_next_entries(

2 TPL_PhoneListProfile o,

3 Environment *_ev,

4 transaction _transaction,

5 long how_many,

6 TPL_PhoneEntryInfoList* entry_list)

7 {

8 tmf_boolean more;

9 SubObjectId it_ref;

10

11 /*

12 * Get the subobject ID from the object

13 * reference. This is the iterator handle.

14 */

15 it_ref = BOA_get_subobject_id(tmf_locate_boa(),

16 _ev, o);

17

18 more = iterator_copy(it_ref, _ev,

19 entry_list, how_many);

20

21 return(more);

22 }

Page 161: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Output Data with Iterators

Application Development with TME 10 ADE 5–21

Creating S

calableO

perations

The implementation, shown above, first decodes the object referenceto extract the iterator handle. The method then calls theiterator_copyfunction to marshal and return the next block of records.

The Iterator EngineTheiterator_copy function underlies all the iterator-based methods inTivoli/Phone. The function takes an iterator handle and returns thenextn records from the profile.

The first thing theiterator_copy function does is get a mutex lock.The lock prevents another iterator request from being serviced duringthe critical period that the function is fetching records. Subsequentcalls toiterator_copy block until the current invocation finishes itstask and frees the lock.1 tmf_boolean iterator_copy(

2 SubObjectId iterator_ref,

3 Environment *_ev,

4 TPL_PhoneEntryInfoList *entries,

5 unsigned long max)

6 {

7 int volatile num = 0;

8 tmf_boolean volatile more = FALSE;

9 tmf_boolean volatile done = FALSE;

10 imp_Phone_iterator *it;

11 TMF_Types_StringList key_list;

12 int index, i;

13 TMF_CCMS_Database_record_list recs;

14 TMF_CCMS_Database_record_item *rec;

15 TPL_PhoneEntryInfo entry;

16

17 /* Get a lock so we don’t get walked on while we copy */

18 pthread_mutex_lock(&Phone_iterator_lock);

Next, the function uses the iterator handle to locate the stateinformation structure.19 Try {

20 it = locate_iterator(iterator_ref, &index);

In this implementation, the state information structure is stored in alinked list, keyed by the iterator handle. The functionlocate_iteratorfinds the state structure in the list and returns it to the caller.

Page 162: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Output Data with Iterators

5–22 Version 3.6

The function uses theTMF_CCMS::Database::dump_some_dbmethod on the profile organizer to get a block of records. The functionuses the key of the last record returned (stored in the state informationstructure) as its starting point.21 while (!done) {

22 seq_init((sequence_t *)&key_list);

23 seq_init((sequence_t *)&recs);

24

25 /*The last key field allows us to begin the

26 * search at the same point we left off

27 */

28 if (it->last_key != NULL) {

29 seq_add((sequence_t *)&key_list,

30 &it->last_key, sizeof(char *));

31 }

32

33 /*

34 * Use the iterative version of dump_some_db to get a

35 * manageable chunk of data to work on.

36 */

37 t_TMF_CCMS_Database_dump_some_db(

38 it->profile_org, _ev, Trans_sub,

39 it->db_name, it->partition, FALSE,

40 CHUNK_SIZE, &key_list, &recs);

After it obtains a block of records, the function must copy them intotheentries output parameter. If the caller defined a search string(through thefind_by_name method), the function compares eachrecord against the string before copying it into the output sequence. Ifno search key was defined,iterator_copy simply copies each record.41 /* Loop through all the records */

42 for (i = 0; i < seq_len((sequence_t *)&recs)

43 && num < max; i++) {

44 rec = (TMF_CCMS_Database_record_item *)

45 seq_get( (sequence_t *)&recs, i,

46 sizeof(TMF_CCMS_Database_record_item));

47

48 ...

49 /*

50 * If the caller specified a search key,

51 * try and make a match.

Page 163: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Output Data with Iterators

Application Development with TME 10 ADE 5–23

Creating S

calableO

perations

52 */

53 if (it->search_name != NULL) {

54 if (strstr(

55 get_name_attr(&(rec->rec.attrs)),

56 it->search_name) != NULL) {

57 convert_nmval_to_entry(

58 &(rec->rec.attrs),

59 &entry);

60 ...

61 /* Add it to the return list */

62 seq_add((sequence_t *)entries,

63 &entry, sizeof(entry));

64 num++;

65 }

66 }

67 else {

68 convert_nmval_to_entry(

69 &(rec->rec.attrs), &entry);

70

71 seq_add((sequence_t *)entries,

72 &entry, sizeof(entry));

73 num++;

74 }

75

76 /* Update the last key field */

77 mg_free(it->last_key);

78 it->last_key = mg_strdup(rec->key);

79 }

80 seq_free_buffer((sequence_t *)&key_list);

The inner loop terminates when it has copied all the records in theblock or when the function has filled its return quota. If the functionhas exhausted the current chunk of records, but not filled the returnquota, execution returns to the top of the main loop. The process offetching blocks of records and copying them to the output buffercontinues until thedump_some_db method returns no records or thefunction fills its quota.

If iterator_copy has filled its quota, it must determine whether thereare still more records to return. The function must check for theboundary condition where the record that completes the quota is alsothe last record to be returned by the iterator.

Page 164: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Output Data with Iterators

5–24 Version 3.6

81 /*

82 * If we got zero records from dump_db,

83 * there are no more records.

84 */

85 if (seq_len((sequence_t *)&recs) == 0) {

86 done = TRUE;

87 more = FALSE;

88 }

89

90 /*

91 * If we filled our buffer we are done, but

92 * we have to see if there are more records.

93 */

94 else if (num == max) {

95 done = TRUE;

96

97 /*

98 * Use dump_some_db to look ahead one record

99 * since we might have conincidentally hit the

100 * edge of our buffer at the same time

101 * we hit our quota.

102 */

103 if (i == seq_len((sequence_t *)&recs)) {

104 /* Look ahead one record */

105 ...

106 t_TMF_CCMS_Database_dump_some_db(

107 it->profile_org,

108 _ev, Trans_sub,

109 it->db_name, it->partition,

110 FALSE, 1, &dummy_key, &dummy);

111

112 if (seq_len((sequence_t *)&dummy)

113 > 0) {

114 more = TRUE;

115 }

116

117 seq_free_buffer((sequence_t *)

118 &dummy_key);

119 ORBfree(&dummy);

120 }

121 else {

122 more = TRUE;

Page 165: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Output Data with Iterators

Application Development with TME 10 ADE 5–25

Creating S

calableO

perations

123 }

124 }

125 }

On exit from the main loop,iterator_copy checks themore flag to seeif there are more records to be returned. Ifmore is FALSE, thefunction frees the state information structure for the iterator. Finally,iterator_copy releases the mutex lock and returns to the caller.126 /* If we are done, destroy the iterator */

127 if (!more) {

128 remove_iterator(it->reference);

129 }

130 }

131 Catch(ExException, ex) {

132 pthread_mutex_unlock(&Phone_iterator_lock);

133 ReThrow;

134 }

135 EndTry;

136

137 /* Unlock the iterator mechanism */

138 pthread_mutex_unlock(&Phone_iterator_lock);

139 return(more);

140 }

Page 166: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Scalable Output Data with Iterators

5–26 Version 3.6

Page 167: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Development with TME 10 ADE 6–1

Profile E

ndpoint Methods

6Profile Endpoint Methods

A profile-based application comprises—at a minimum—profileobjects and the behavior for the endpoint. In the workflow diagram ofthe Tivoli/Phone application, for example, the phone list represents aprofile object and the department members’ machines represent profileendpoints.

As you read in Chapter 1, “Anatomy of a TME 10 ADE Application,”the Tivoli/Phone application requires the following behavior from itsendpoint objects:

■ It must be able to subscribe to receive phone list updates (basicprofile endpoint behavior).

■ It must be able to convert a phone list database into a file that canbe imported into a personal organizer application.

■ It must be able to import an export file from a personal organizerapplication into a phone list database.

6

Phone ListDatabase

Department Members

Distribute

Page 168: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Profile Endpoint Behavior

6–2 Version 3.6

Profile Endpoint BehaviorThe endpoint class in the Tivoli/Phone application is calledPhoneEndpoint. ThePhoneEndpoint class implements theoperations defined by theplbo interface:1 interface plbo : TMF_SysAdmin::PolicyDrivenBase {

2

3 void discover_phonelist(

4 in string filename,

5 out TPL::PhoneEntryInfoList phone_list);

6

7 void update_phone(

8 in any data,

9 in TMF_Types::OctetList dkey,

10 out TMF_Types::OctetList dout);

11 };

The interface defines two operations:discover_phonelist andupdate_phone. Thediscover_phonelist operation reads an importfile and returns a list of phone list entries. Theupdate_phoneoperation does the converse; it takes a list of entries and converts themto an export file format.

Theplbo interface defines operations that satisfy two of the three basicbehaviors of Tivoli/Phone’s endpoint class. The other behavior (theability to subscribe to receive profile updates) comes from inheritingtheProfileEndpoint interface, which is defined by TME 10 ADE.

The simplest way to get basic profile endpoint behavior is to have yourinterface inherit from theProfileEndpoint interface. However, if yourapplication’s endpoint objects correspond one-for-one with nodes inthe TME 10 installation, you can use theManagedNode object as yourprofile endpoint. Using theManagedNode object as the profileendpoint provides two advantages:

■ TheManagedNode object implements a user interface throughwhich users could access profile data at the endpoint. If youdefine your own endpoint, you will need to implement a userinterface for it.

■ EachManagedNode object resides on the host it represents. Ifyou use theManagedNode object as your endpoint, yourendpoint operations will execute on that host, instead of on the

Page 169: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Profile Endpoint Behavior

Application Development with TME 10 ADE 6–3

Profile E

ndpoint Methods

TME 10 server. If you define your own endpoint class and wantsimilar distributed endpoint behavior, you must handle creatingeach endpoint on the correct host.

The above is true for theManagedNode object, but not for theEndpoint object. TheEndpoint object has no user interface. It does,however, have behavior.

How do you add application endpoint behavior to an existing endpointclass likeManagedNodeor Endpoint? TME 10 provides a commandcalledwinstendpt for installing application-specific endpoint classes.The installation specification for thePhoneEndpoint class executesthewinstendpt command when the class is added to TME 10.1 #!/bin/sh

2 imp_plbo_CO=$1

3 METHODPATH=$2

4

5 FriendlyClass="PhoneEndpoint"

6 set_friendly_name $imp_plbo_CO $FriendlyClass

7

8 BEHAVIOR=`objcall $imp_plbo_CO _get_behavior`

9

10 CLO=`wlookup Library`

11

12 ep_class_name="ManagedNode"

13 EP_CLASS=`objcall $CLO _lookup_object $ep_class_name`

14 status=$?

15 if [ $status -eq 0 ]; then

16 EP_BEHAVIOR=`objcall $EP_CLASS _get_behavior`

17 objcall $EP_BEHAVIOR oi_add $BEHAVIOR ''

18 TRUE FALSE 0 0

19 fi

Thewinstendpt command adds the application endpoint behavior totheManagedNode class and theEndpoint class.ManagedNodeand

The Endpoint ClassTheEndpoint object does not have a GUI and state as does theManagedNode object. It does have behavior, as does theManagedNode object.

Page 170: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Importing Profile Records

6–4 Version 3.6

Endpoint objects then have access to the methods and attributes of theapplication’s class.

Importing Profile RecordsAll profile-based objects inherit an operation calledpopulate from theTMF_CCMS::Profile interface. Each application must provide itsown implementation for the operation. Thepopulate operation seedsa profile with records from an external source, such as an import file.See Chapter 4, “Implementations for CCMS Methods,” for adiscussion of the Tivoli/Phone implementation ofpopulate.

Many implementations ofpopulate use a separate “discovery” methodto perform the actual parsing of the import file. Keeping the parserseparate from thepopulate implementation allows you to support avariety of import formats without hard-coding them into thepopulatemethod. In the case of Tivoli/Phone, the discovery method,discover_phonelist, is defined by the profile endpoint.

Profile

populateImplementation

Profilediscover_phonelist

ExternalFile

Endpoint

Object

Page 171: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Importing Profile Records

Application Development with TME 10 ADE 6–5

Profile E

ndpoint Methods

The IDL signature ofdiscover_phonelist is shown below.

void discover_phonelist( in string filename, out PhoneEntryInfoList list);

The import file used by Tivoli/Phone is a text file. Each line of the filecomprises a single phone list entry. The entry’s fields are delimited bycolons and have fixed positions on the line:

name:phone:addr:city:state:country:post:owner:type:desc

Only the name and phone fields are required. The remaining fields canbe left empty or omitted completely. For example, the following arevalid entries in an import file:

Babe Ruth:555-1212:713 Swat Ln:New York:NY:USA:72273

Othello:933-0293:394 Tragedy Ave:Milan::Italy::Vendor:Fax

Robert Bruce:071-555-3342

The implementation ofdiscover_phonelist for theManagedNodeobject uses the TME 10 ADE file I/O routines to open and read thespecified import file. For theEndpoint object and LCF, it uses thestdio APIs inlibc. The method parses each line of the file and convertsit into aPhoneEntryInfo structure. The parser function,parse_line,breaks each line into tokens and sets the appropriate fields of thestructure.1 #ifdef ENDPOINT_BUILD

2 #include <time.h>

3 #include <mrt/tiv_mrt.h>

4 #include <cpl/systhread.h>

5 #include “ppo_defs.h”

6 #include “t_plbo.h”

7 #include “phone_msgs.h”

8 #include “plbo_lcf.h”

Parameter Purpose

filename Path to the import file

list Sequence of entries from the import file

Page 172: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Importing Profile Records

6–6 Version 3.6

9 #include “plbo_lcf_msgs.h”

10 #include “plbo_lcfExMacros.h”

11 /* temporary hacks */

12 #define istream_t FILE

13 #else

14 #include <tivoli/t_plbo.h>

15 #include <tivoli/t_plbo_imp.h>

16 #include “tivoli/ppo_defs.h”

17 #include <tivoli/ExException.h>

18 #include <tivoli/sequence.h>

19 #include <tivoli/fstream.h>

20 #endif

21 #include <string.h>

22

23 #ifdef ENDPOINT_BUILD

24 #define EMPTY_STR ““

25 #include “phoneExMacros.h”

26 #include “plbo_msgs.h”

27 #include “seqmap.h”

28 #else

29 #define EMPTY_STR ““

30 #include <tivoli/phoneExMacros.h>

31 #include “plbo_msgs.h”

32 #endif

33

34 static void parse_line(char *, TPL_PhoneEntryInfo *);

35 static char *tokenize(char *, const char *);

36 static void set_field(TPL_PhoneEntryInfo *, int , char*);

37

38 /*

39 * Name: t_imp_plbo_discover_phonelist

40 *

41 * Purpose: Implementation of the discover_phonelist

42 * method.

43 *

44 * This method implementation is called when

45 * a profile is populated. It looks for a

46 * “system” file on a given managed node to

47 * discover. The text file must have the

48 * following format for each entry:

49 * name:phone:address:city:state:country:zip:owner:

Page 173: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Importing Profile Records

Application Development with TME 10 ADE 6–7

Profile E

ndpoint Methods

50 * type:comment

51 */

52 void t_imp_plbo_discover_phonelist(

53 plbo source,

54 Environment *_ev,

55 transaction _transaction,

56 char *filename,

57 TPL_PhoneEntryInfoList *phone_list)

58 {

59

60 istream_t * volatile fp = NULL;

61 char *line = NULL;

62 TPL_PhoneEntryInfo entry;

63 char buf[BUFSIZ];

64 char *ptr = buf;

65 int volatile line_num = 0;

66 int check_for_error = 0;

67

68 memset(&entry, 0, sizeof(entry));

69 seq_init((sequence_t *)phone_list);

70

71 /* Open the phone list source file */

72 #ifdef ENDPOINT_BUILD

73 if ((fp = fopen(filename, “r”)) == NULL) {

74 vaThrow(CatSpec(plbo_msgs, file_open_err),

75 “fopen(%1$s, r) failed\n”, filename);

76 }

77 #else

78 Try {

79 fp = ifstream_create(filename, 0, 10,no_splice);

80 }

81 CatchAll() {

82 ReThrow;

83 }

84 EndTry;

85 #endif

86

87 #ifdef ENDPOINT_BUILD

88 /*

89 * Can’t seem to trust feof()/ferror() on Netware. Just

90 * let fgets() flag EOF on Netware.

Page 174: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Importing Profile Records

6–8 Version 3.6

91 */

92 # ifdef NW

93 while (TRUE)

94 # else

95 while (!feof(fp) && !ferror(fp))

96 # endif

97 #else

98 while (!istream_eof(fp))

99 #endif

100 {

101 memset(&entry, 0, sizeof(entry));

102 #ifdef ENDPOINT_BUILD

103 cpl_THREADyield(0);

104 /* mostly for Netware’s benefit */

105 if ((line = fgets(ptr, sizeof (buf), fp)) ==NULL) {

106 /*

107 * why would we get NULL after feof() already was

108 * tested for? It can happen on Netware....

109 */

110 check_for_error = 1;

111 break;

112 }

113 #else

114 line = istream_get_line(fp, &ptr);

115 #endif

116 line_num++;

117

118 if (!line || strlen(line) == 0 || *line == ‘\n’){

119 continue;

120 }

121

122 Try {

123 parse_line(line, &entry);

124 }

125 Catch(ExFailed, ex) {

126 free_entry_struct(&entry);

127 memset(&entry, 0, sizeof(entry));

128 }

129 Catch(ExException, ex) {

130 char num_str[10];

Page 175: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Importing Profile Records

Application Development with TME 10 ADE 6–9

Profile E

ndpoint Methods

131 ExPhoneError2 *ex1;

132

133 free_entry_struct(&entry);

134 memset(&entry, 0, sizeof(entry));

135

136 sprintf(num_str, “%d”, line_num);

137 #ifdef ENDPOINT_BUILD

138 vaThrow(CatSpec(plbo_msgs, parse_error),

139 “There was a parse error in %1$s on line%2$d”,

140 filename, line_num);

141

142 #else

143 ex1 = (ExPhoneError2 *)

144 ExPhoneError2New(plbo_msgs,

145 parse_error,

146 filename,

147 num_str);

148 ContextThrow(ex1->type_name, ex1);

149 #endif

150 }

151 EndTry;

152

153 /* If the line doesn’t at least contain a name andphone,

154 * skip it.

155 */

156 if (entry.name == NULL || entry.phone == NULL) {

157 continue;

158 }

159

160 seq_add((sequence_t *)phone_list, &entry,

161 sizeof(entry));

162 }

163

164 #ifdef ENDPOINT_BUILD

165 #ifndef NW

166 /*

167 * Check for file read error -- except on Netware

168 */

169 if (check_for_error && ferror(fp)) {

170 int err = ferror(fp);

Page 176: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Importing Profile Records

6–10 Version 3.6

171

172 fclose(fp);

173

174 vaThrow(CatSpec(plbo_msgs, parse_error),

175 “Unexpected error found while parsing %1$s(e=%2$d)”,

176 filename, err);

177 }

178 #endif

179

180 fclose(fp);

181 #endif

182 }

183

184 /*

185 * Name: parse_line

186 *

187 * Purpose: Parses a line from a phonelist file.

188 *

189 * Description: This function parses a delimited text

190 * line and returns a phone structure.

191 * The line must have the following format:

192 * name:phone:address:city:state:country:zip:owner:

193 * type:comment

194 *

195 * The name and phone are required. Others can be

196 * ommitted.

197 */

198 static void parse_line(char *line, TPL_PhoneEntryInfo*entry)

199 {

200 char *ptr;

201 int i = 0;

202

203 if (line == NULL) {

204 Throw(ExFailed_new(“parse_line”));

205 }

206

207 /*

208 * If the line is blank, we don’t want any part of it.

209 */

210 if (strlen(line) == 0 || *line == ‘\n’) {

Page 177: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Importing Profile Records

Application Development with TME 10 ADE 6–11

Profile E

ndpoint Methods

211 Throw(ExFailed_new(“parse_line”));

212 }

213

214 /*

215 *Strip off any new line character at end of the line.

216 */

217 if ((ptr = strrchr(line, ‘\n’)) != NULL) {

218 *ptr = ‘\0’;

219 }

220

221 for (ptr = line; (ptr = tokenize(ptr, “:”)) != NULL;i++, ptr = NULL) {

222 if (strlen(ptr) > 0) {

223 set_field(entry, i, ptr);

224 }

225 }

226

227 /* Fill in the remaining fields with empty strings */

228 for (; i < 10; i++) {

229 set_field(entry, i, ““);

230 }

231

232 entry->flags = PP_ALL_FIELDS;

233 }

234

235 /*

236 * Name: set_field

237 *

238 * Purpose: Sets the field of a phone structure based on

239 * a line token and a field number.

240 *

241 */

242 static void set_field(TPL_PhoneEntryInfo *entry, intindex,

243 char *ptr)

244 {

245 switch (index) {

246 /* Name */

247 case 0:

248 entry->name = mg_strdup(ptr);

249 break;

250

Page 178: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Importing Profile Records

6–12 Version 3.6

251 /* Phone */

252 case 1:

253 entry->phone = mg_strdup(ptr);

254 break;

255

256 /* Address */

257 case 2:

258 entry->address = mg_strdup(ptr);

259 break;

260

261 /* City */

262 case 3:

263 entry->city = mg_strdup(ptr);

264 break;

265

266 /* State */

267 case 4:

268 entry->state = mg_strdup(ptr);

269 break;

270 /* Country */

271 case 5:

272 entry->country = mg_strdup(ptr);

273 break;

274

275 /* Postal Code */

276 case 6:

277 entry->postal = mg_strdup(ptr);

278 break;

279

280 /* Owner */

281 case 7:

282 if (strlen(ptr) > 0) {

283 entry->owner = string_to_owner(ptr);

284 }

285 else {

286 entry->owner = 0;

287 }

288 break;

289

290 /* Type */

291 case 8:

292 if (strlen(ptr) > 0) {

Page 179: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Importing Profile Records

Application Development with TME 10 ADE 6–13

Profile E

ndpoint Methods

293 entry->type = string_to_phonetype(ptr);

294 }

295 else {

296 entry->owner = 0;

297 }

298 break;

299

300 /* Comment */

301 case 9:

302 entry->comment = mg_strdup(ptr);

303 break;

304

305 default:

306 /* NOP */

307 break;

308 }

309 }

310

311 /*

312 * Name: tokenize

313 *

314 * Purpose: Returns the next token from a

315 * colon-delimited text line.

316 *

317 */

318 static char *tokenize(char *buff, const char *delims)

319 {

320 static char *ptr = NULL;

321 char *back;

322

323 /*

324 * If buffer is NULL, we’re starting over.

325 */

326 if (buff != NULL) {

327 ptr = buff;

328 }

329 else if (ptr == NULL) {

330 return (NULL);

331 }

332

333 back = ptr;

334

Page 180: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Post-distribution Processing

6–14 Version 3.6

335 for (; *ptr != ‘\0’ && strchr(delims, *ptr) == NULL;ptr++) {

336 #ifdef ENDPOINT_BUILD

337 cpl_THREADyield(0);/* mostly for Netware’sbenefit */

338 #endif

339 }

340

341 /*

342 * One way or another, we’ve hit the end of the string.

343 */

344 if (*ptr == ‘\0’) {

345 if (ptr - back > 0) {

346 ptr = NULL;

347 return(back);

348 }

349 else {

350 ptr = NULL;

351 return(NULL);

352 }

353 }

354

355 *ptr = ‘\0’;

356 ptr++;

357

358 return(back);

359 }

360

Post-distribution ProcessingWhen a user distributes a profile to its subscribers, CCMS invokes anapplication-defined method to perform any necessary post-processing.Your application registers thisendpoint method when it creates a newprofile database. See theinitializ implementation in Chapter 2,“Defining an Application with IDL.”

When your application create a new profile database, the applicationalso registers a method that is run whenever a profile is distributed toan endpoint. This method is responsible for performing any furthermanipulation of the profile data. For example, a user management

Page 181: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Post-distribution Processing

Application Development with TME 10 ADE 6–15

Profile E

ndpoint Methods

application might register a method that converts the profile data into/etc/passwd entries.

One important advantage of the post-distribution processing method isthat it provides a way to operate in a heterogenous environment. Anapplication can store profile data in a generic format and use theendpoint method to convert the data into a platform-specific format.For example, a printer application might store its configurationinformation in a platform-independent format. The application’sendpoint method would be responsible for determining the platformtype and converting the data into the correct format (/etc/printcap andso on).

In the Tivoli/Phone application, heterogeneity is not really an issue.The purpose of the post-distribution method in this case is to convertthe profile data into a file that users can import into their personalorganizer applications. The IDL signature of the operation, calledupdate_phone, is shown below.

void update_phone(any data, TMF_Types::OctetList dkey, TMF_Types::OctetList dout);

Theupdate_phone method first gets a transaction lock to ensure thatthe method has exclusive access to the export file.

Parameter Purpose

data Optional application-specific data

dkey Key of an MDist channel

dout Return data (application-defined)

LCF Endpoints and TransactionsTransactions are not supported for objects in theEndpoint class (LCFendpoints), so the following code applies only toManagedNodeobjects.

Page 182: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Post-distribution Processing

6–16 Version 3.6

1 void t_imp_plbo_update_phone(

2 plbo o,

3 Environment *_ev,

4 transaction trans,

5 any* data,

6 TMF_Types_OctetList* dkey,

7 TMF_Types_OctetList* dout)

8 {

9 TMF_CCMS_Propagation_update_params up;

10 TMF_CCMS_Database_record_list recs;

11 TMF_CCMS_Database_record_item *rec;

12 TPL_PhoneEntryInfoList current, entries;

13 sequence_t *unique = NULL;

14 int i;

15 #ifdef ENDPOINT_BUILD

16 void *chan;

17 FILE * volatile fp = NULL;

18 #else

19 iom_handle_t *chan;

20 ofstream_t * volatile fp = NULL;

21 #endif

22 Environment ev = {0};

23 TPL_PhoneEntryInfo entry;

24 any notice_any;

25 char *endpoint_name;

26 tmf_msg_t *msg;

27 unsigned long error = 0;

28 #ifdef ENDPOINT_BUILD

29 struct stat file_stat = {0};

30 type_repository* t[3];

31

32 t[0] = phone_type_repository;

33 t[1] = plbo_type_repository; /* this probably alreadydone by main() */

34 t[2] = type_repository_null;

35 adr_type_init(t);

36 #else

37 TMF_ManagedNode_t_stat stat = {0};

38 #endif

39

40 /*

41 * Initialize the return buffer. This method does not

Page 183: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Post-distribution Processing

Application Development with TME 10 ADE 6–17

Profile E

ndpoint Methods

42 * currently return any information.

43 */

44 seq_init((sequence_t *)dout);

45 seq_init((sequence_t *)&current);

46 seq_init((sequence_t *)&entries);

47 memset(&entry, 0, sizeof(TPL_PhoneEntryInfo));

48

49 #ifndef ENDPOINT_BUILD

50 /*

51 * Get a transaction lock.

52 */

53 tmf_trans_begin(OC_SUB_T);

54 transaction_lock(tmf_current_transaction(),

55 &ev,

56 “endpoint_update”,

57 lock_write,

58 20);

59 #endif

60

Since the number of records passed to the endpoint method can bearbitrarily large, CCMS does not pass them as a parameter to theendpoint method. CCMS sends the records to the endpoint methodthrough amultiplexed distribution (MDist) channel.

The endpoint method receives a key to an MDist channel. TME 10ADE provides two convenience functions to open the channel andreceive the records. The first function,ccms_read_update_parameters, opens the MDist channel andreturns a data structure that contains information about the distribution(for example, whether local modifications are to be preserved). Thesecond function,ccms_read_pushed_records, reads the MDistchannel and returns the records that were transmitted by CCMS.61 /*

62 * Open the MDist channel to the push method and

63 * get the push information

64 */

65 chan = ccms_read_update_parameters(dkey, &up);

66

67 /* Now get all the pushed records */

68 ccms_read_pushed_records(chan, &recs);

Page 184: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Post-distribution Processing

6–18 Version 3.6

Theupdate_phone method iterates over the sequence of records,converting each to aPhoneEntryInfo structure. The method ignoresany records that have either ther_deleted or r_blocked flag set, sincethose records do not belong in the export file.69 /*

70 * Go through all the entries we have and convert them

71 * to phone list structures.

72 */

73 for (i = 0; i < seq_len((sequence_t *)&recs); i++) {

74 #ifdef ENDPOINT_BUILD

75 cpl_THREADyield(0); /* mostly for Netware’s benefit */

76 #endif

77 rec = (TMF_CCMS_Database_record_item *) seq_get(

78 (sequence_t *) &recs, i,

79 sizeof(TMF_CCMS_Database_record_item));

80 if (strstr(rec->key, DEF_TAG) || strstr(rec->key,VAL_TAG)) {

81 continue;

82 }

83

84 /* If the record was deleted, skip it */

85 if (rec->rec.flags & TMF_CCMS_Database_r_deleted

86 || rec->rec.flags &

87 TMF_CCMS_Database_r_blocked) {

88 continue;

89 }

90

91 /*

92 * Convert to a phone structure and add it to the list.

93 */

94 memset(&entry, 0, sizeof(TPL_PhoneEntryInfo));

95 convert_nmval_to_entry(&(rec->rec.attrs),

96 &entry);

97 seq_add((sequence_t *)&entries, &entry,

98 sizeof(TPL_PhoneEntryInfo));

99 }

100

CCMS uses aforce level during distribution to determine how tomerge records into the profile database on the endpoint. Theforce_alllevel causes the incoming records to completely overwrite the existingrecords, including existing records that do not have a corresponding

Page 185: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Post-distribution Processing

Application Development with TME 10 ADE 6–19

Profile E

ndpoint Methods

record in the incoming set. Theno_force level maintains all uniqueexisting records. In cases where an existing record and an incomingrecord have the same key, CCMS uses the profile’s conflict policy todetermine which record to keep. See theApplication Services Manual,Vol. II, for information about conflict policy.

The Tivoli/Phone implementation ofupdate_phone also supports theconcept of force level. If the force level isforce_all, the methodcompletely overwrites the export file—if it exists. If the force level isno_force, the method preserves unique local entries in the export file.Although it is debatable whether this behavior is necessary inTivoli/Phone, it does make sense in some systems managementapplications. In a printer configuration application, for example, youmight preserve printer entries that were added by an outside utility,such assam on HP-UX. You could even implement your endpointmethod so that it could detect unique entries in the managed file andcreate corresponding entries in the endpoint profile database.

The Tivoli/Phone endpoint method usesdiscover_phonelist todetermine if there are any existing entries in the export file. Themethod then uses theseq_diff function to get a list of entries that existin the file but not in the profile database. The method appends theunique entries to the sequence it obtained from CCMS to complete thelist of entries.101 /*

102 * If the subscriber is allowed to maintain local info,

103 * read the current file so we can find out where the

104 * intersection is.

105 *

106 * If the file doesn’t exist or contains a syntax error,

107 * we will ignore the exception and proceed as though

108 * this were a “force all” push.

109 *

110 * An interesting note: we call this method as

111 * trans_revocable

112 * instead of trans_sub, so that if the method throws

113 * an exception, it will not automatically abort our

114 * transaction.

115 */

116 if (up.forceflag != TMF_CCMS_Propagation_force_all) {

117 Try {

Page 186: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Post-distribution Processing

6–20 Version 3.6

118 #ifdef ENDPOINT_BUILD

119 t_imp_plbo_discover_phonelist(o,

120 ev,

121 trans_revocable,

122 ENDP_FILE,

123 &current);

124 #else

125 t_plbo_discover_phonelist(o,

126 _ev,

127 trans_revocable,

128 ENDP_FILE,

129 &current);

130 #endif

131 }

132 CatchAll() {

133 }

134 EndTry;

135 }

136

137 /*

138 * Get a list of file contents that

139 * do not appear in the push list (if we

140 * are preserving local entries).

141 */

142 if (seq_len((sequence_t *)&current)) {

143 unique = seq_diff((sequence_t *)&entries,

144 (sequence_t *)&current,

145 sizeof(TPL_PhoneEntryInfo),

146 cmp_phone_key);

147

148 seq_append((sequence_t *)&entries, unique,

149 sizeof(TPL_PhoneEntryInfo));

150 }

All that remains is to open the export file and write out the entries. Themethod truncates the file so thatupdate_phone can start with anempty file. Thewrite_entries_to_file function converts eachPhoneEntryInfo structure entries into colon-delimited lines of textand writes it to the export file.151 /* Open the export file for writing */

152 #ifdef ENDPOINT_BUILD

153 if ((fp = fopen(ENDP_FILE, “w”)) == NULL)

Page 187: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Post-distribution Processing

Application Development with TME 10 ADE 6–21

Profile E

ndpoint Methods

154 vaThrow(CatSpec(plbo_msgs, open_endp_failed),

155 “Could not open the file %1$s on the endpoint(e=%2$d).”,

156 ENDP_FILE, errno);

157 #else

158

159 Try {

160 fp = ofstream_create(ENDP_FILE, IOS_TRUNC, 30);

161 }

162 CatchAll() {

163 ExPhoneError *ex;

164 ex = (ExPhoneError *)ExPhoneErrorNew(

165 plbo_msgs,

166 open_endp_failed);

167 ContextThrow(ex->type_name, ex);

168 }

169 EndTry;

170

171 /* Write the output file */

172 write_entries_to_file(fp, &entries);

After all the records have been written to the export file,update_phone destroys the file handle with eitherios_destroy (for aManaged Node) orfclose (for an endpoint) and logs a notice to recordthe update of the export file.173 #ifdef ENDPOINT_BUILD

174 fclose(fp);

175 #else

176 ios_destroy(fp);

177 #endif

178

179 /* Log the notice */

180 endpoint_name =

181 t_SysAdmin_PolicyDrivenBase__get_label(

182 obj, &ev, Trans_sub);

183

184 memset(&notice_any, 0, sizeof(notice_any));

185 notice_any._type = TC_string;

186 notice_any._value = &endpoint_name;

187

188 #ifndef ENDPOINT_BUILD

189 /* do notice groups work from LCF EP? */

Page 188: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Post-distribution Processing

6–22 Version 3.6

190 msg = tmfMsgNew(plbo_msgs,

191 endpoint_success,

192 notice_any);

193

194 tmf_msg_log(msg, NOTICE_GROUP, TMF_Notice_Notice);

195 tmf_msg_destroy(msg);

196

197 tmf_trans_end();

198 #endif

199 }

You might have noticed that the method does not free the transactionlock that it obtained at the beginning of the implementation.Transaction locks that are not freed are “promoted” to the method’sparent. The lock continues to be promoted until it reaches a methodthat was invoked as a top-level transaction. When the top-level methodcompletes, the lock is automatically freed.

Transactions Are Not Supported on EndpointsThe remaining discussion of transactions applies only to ManagedNodes, not to LCF endpoints.

C

B

A

D

Lock freed when Acompletes

Page 189: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Post-distribution Processing

Application Development with TME 10 ADE 6–23

Profile E

ndpoint Methods

In the picture above, method C obtains a transaction lock that ispromoted to its parent, method B. Since method B is a sub-transactionof method A, the lock is promoted to A when B completes. The lock isonly freed when method A completes.

Of course, a method is not required to promote its lock to its parent.TME 10 ADE provides an operation to release a transaction lock. SeetheApplication Services Manual, Vol. I, for more information abouttransaction locks.

Page 190: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Post-distribution Processing

6–24 Version 3.6

Page 191: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Development with TME 10 ADE 7–1

Creating an A

pplicationU

ser Interface

7Creating an Application UserInterface

Each authorized TME 10 administrator has access to a TME 10desktop. The TME 10 desktop (also called the user interface, or UI,server), ties together all of the applications and services provided byTME 10. Administrators use the desktop to manage the TME 10installation and to launch TME 10 applications. TME 10 ADEprovides a set ofdesktop services that you can use to integrate yourapplication with the TME 10 desktop.

In this chapter, we will look at the Tivoli/Phone graphical interface andhow it uses the TME 10 ADE desktop services to implement itsinterface.

7

No GUI for Endpoint ObjectsLCF endpoints, represented by theEndpoint object class, do notsupport a GUI or command-line interface. The information in thischapter applies only to theManagedNode object.

Page 192: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The Tivoli/Phone Graphical Interface

7–2 Version 3.6

The Tivoli/Phone Graphical InterfaceThe graphical part of the Tivoli/Phone application’s user interfacecomprises three main dialogs and a host of small support dialogs. Themain dialog of the user interface is the properties window. The windowis displayed when a user double-clicks on a profile icon.

The central focus of the dialog is a table that shows the contents of theprofile’s database. Buttons along the bottom of the window providesome commonly used operations, such as adding, removing, andediting profile entries. The window also sports three pull-down menusthat provide additional options for manipulating the profile data orhow the data is displayed.

Page 193: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The Tivoli/Phone Graphical Interface

Application Development with TME 10 ADE 7–3

Creating an A

pplicationU

ser Interface

Pressing theAdd... button at the bottom of the window displays a formthat a user fills out to create a new profile entry.

The user completes the form and pressesAdd & Close or Add tocreate the new entry. The application reads the values entered by theuser and uses them to create aPhoneEntryInfo structure for the newentry. The application also automatically updates the table on theprofile properties window to show the new entry.

The user follows a similar procedure for editing a profile entry. Theuser selects a row and presses theEdit... button to edit an entry. The

Page 194: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The Tivoli/Phone Graphical Interface

7–4 Version 3.6

application displays the form dialog, already filled with the selectedentry’s information.

The user can change the entry’s information, except the name andphone number. PressingChange & Close or Change updates theassociated record in the profile database. The applicationautomatically updates the table on the profile properties window toreflect the change.

In addition to the three dialogs shown above, the Tivoli/Phonegraphical interface also includes numerous smaller support dialogs.These support dialogs fall into two categories: those that manipulatethe profile object itself and those that manipulate how the profile datais displayed in the properties window. The dialogs in the first categoryare listed below:

■ Distribute—Distributes the profile to a user-selected set ofsubscribers.

■ Distribution Defaults—Changes the default settings that areused during a distribution.

■ Get New Copy—On a local copy of a profile, pulls a new copyof the profile database from the original profile.

Page 195: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The Tivoli/Phone Graphical Interface

Application Development with TME 10 ADE 7–5

Creating an A

pplicationU

ser Interface

■ Populate — Populates the profile database with records, using animport file as the source.

■ Go to Profile — Navigates between copies of a profile in adistribution hierarchy.

■ Edit Default Policies— Sets default policy for profile attributes.

■ Edit Validation Policies — Sets validation policy for profileattributes.

■ Validate — Checks the profile records against current validationpolicy and reports any records that do not meet policy.

■ Copy Records— Copies records in the current profile databaseto another profile.

■ Move Records— Moves records in the current profile databaseto another profile.

The application also provides dialogs through which a user canmanipulate the appearance of the table control in the profile propertieswindow:

■ Find Records— Searches for records that match a givencriterion.

■ Sort Records— Sets the table column by which the records inthe table are sorted.

■ Sort Attributes — Controls the arrangement of the columns inthe table.

TME 10 ADE provides standard implementations for the dialogsthrough the Table Manager library (see “Using the TME 10 SupportDialogs” on page 7-43 for more information).

Page 196: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Components of a Graphical Interface

7–6 Version 3.6

Components of a Graphical InterfaceA user interacts with a TME 10 ADE application through icons anddialogs. Icons are bitmaps that represent application resources on theTME 10 Desktop. For example, the icon shown below is from theTivoli/Phone application and represents a phone profile object.

Icons perform several important functions:

■ They help a user distinguish between types of resources.Furthermore, since each icon has its own unique label, a user caneasily find a specifc object.

■ They provide visual clues to the state of the object. You candefine several states for an object and assign a different bitmap toeach one. For example, a bulletin board icon might have two iconstates: one if there are no unread notices (an empty bulletinboard) and one if there are unread notices (a bulletin board withnotes on it).

■ They provide a mechanism for interacting with theunderlying object. An icon is usually how a user activates theapplication’s user interface. In the Tivoli/Phone application, forexample, double-clicking on the icon of a phone profile brings upa dialog so the user can edit the contents of the profile.

Page 197: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Components of a Graphical Interface

Application Development with TME 10 ADE 7–7

Creating an A

pplicationU

ser Interface

DialogsWhile icons are a way of representing application resources, dialogsare the mechanism by which users manipulate the state and propertiesof a resource. Dialogs are actually collections of controls (also calledgadgets), such as buttons, lists, and tables. Users can interact with theapplication by changing the state of the controls on the dialog(selecting from a list, for example).

Every control supports a set of attributes that affect how the gadgetlooks and behaves. The exact set of supported attributes depends onthe type of control. All controls, however, support aName attributethat assigns a unique internal name to the control. The name of acontrol is important since it is the handle by which the application canaccess and manipulate the control.

A control’s attributes can be changed by user input orprogrammatically by an application. For example, an applicationmight make a button insensitive (also called “grayed out”) in responseto a user action. In that case, the application would set theSensitiveattribute of the button control toNO. An application manipulates thecontrols in a dialog through the gadget library, which is described laterin this chapter.

List controls

CommandButton controls

Page 198: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Components of a Graphical Interface

7–8 Version 3.6

To construct a dialog, you must create a descriptor for it. A dialogdescriptor is a binary file that defines:

■ The controls that appear in the dialog

■ The layout and placement of controls in the dialog

■ The actions that are taken based on user input (such as when auser selects a button control)

■ Variables that are to be passed to the dialog when it is displayed

You can create dialog descriptors using the Dialog SpecificationLanguage (DSL) or interactively with the Tivoli/Visual DSL tool. DSLis a declarative language that describes a dialog programmatically. InDSL, you describe each control on a dialog as a block of attributes.The snippet of DSL below shows the declaration for aButton control:

Button { Name = set_and_close; Title = "Set & Close"; Commands = change_value&($new_value), destroy&.:();}

See theDesktop Services Manual for a complete introduction to DSL.You can also refer to the Tivoli/Phone source code for example DSLcode.

Dialog StatesAn instance of a dialog can exist in one of three states:

■ Undefined — The dialog has not been posted (loaded) fordisplay.

■ Posted — The dialog has been loaded by the Tivoli UI server, butis not yet visible to the user.

Page 199: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Components of a Graphical Interface

Application Development with TME 10 ADE 7–9

Creating an A

pplicationU

ser Interface

■ Visible — The dialog has been presented to the user and isavailable for user interaction.

There are four actions that change the state of a dialog:

■ Posting an undefined dialog causes the Tivoli UI server to loadthe dialog descriptor and prepare it for display. The dialog isinitially invisible so that the application can initialize anycontrols before presenting the dialog to the user.

■ Presenting a (posted) dialog makes it visible. This makes thedialog available to the user for input.

■ Dismissing a visible dialog returns it to a defined yet invisiblestate. Dialogs are usually dismissed by the user.

■ Freeing a dialog returns it to the undefined state. A dialog can bein either the posted or visible state when it is freed. If the dialogis visible, TME 10 pops down the dialog before freeing it.

Presentation ObjectsDialogs are defined on a per-class basis, so all instances of a particularclass share the same set of dialog descriptors. The dialog descriptorsare located on a presentation object that is associated with the class.The presentation object, which is an instance of theTMF_UI::Presentation class, stores all the dialog descriptors, icons,and bitmaps that make up the object’s user interface. When an objectmust display a dialog, TME 10 automatically fetches the dialog

PostedPresent

Dismiss

Free FreePost

Visible

Undefined

Page 200: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Components of a Graphical Interface

7–10 Version 3.6

descriptor from the presentation object and creates an instance of thedialog.

A class creates its presentation object when the class is installed in theTME 10 environment, usually as part of the installation specification.The command to create a presentation object is calledinitpres. Theinitpres command creates a presentation object and populates it witha list of dialog descriptors, bitmaps, and icon states. An icon state is anamed state that an instance of a class can support, and an iconassociated with that state. To use the TME 10 bulletin board as anexample, the object can have two icon states: one if there are no unreadnotices and one if there are unread notices.

The initpres command for thePhoneListProfile class defines threedialogs (phone_props, add_dialog, andedit_dialog), three bitmaps(phone_icon, locked, andfixed), and one icon state (normal).1 initpres $imp_phone_CO -class -create \

2 dialog phone_props $METHODPATH/phone_props.d \

3 dialog add_dialog $METHODPATH/add_dialog.d \

4 dialog edit_dialog $METHODPATH/edit_dialog.d \

5 bitmap phone_icon xpm $METHODPATH/phone_icon.xpm \

6 bitmap locked xpm $METHODPATH/locked.xpm \

7 bitmap fixed xpm $METHODPATH/fixed.xpm \

Notices Received Notices Read

state=no_unread

state=unread

Page 201: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Components of a Graphical Interface

Application Development with TME 10 ADE 7–11

Creating an A

pplicationU

ser Interface

8 state normal $METHODPATH/phone_icon.d xpm \

9 $METHODPATH/phone_icon.xpm \

10 parent TableMgrGuiDlgs

Presentation objects can inherit dialogs, bitmaps, and icon states fromother presentation objects. In the case of Tivoli/Phone shown above,thePhoneListProfile presentation objects inherits from thepresentation object for theTableMgrGuiDlgs class. As you will readlater (“Using the TME 10 Support Dialogs” on page 7-43), theTableMgrGuiDlgs presentation object contains standardimplementations for many support dialogs, such as for finding andsorting profile records.

CallbacksAn application’s dialogs and windows communicate with theapplication throughcallbacks. A callback is an operation that is tied toa control on a dialog or window. When the user selects or changes thestate of a control, TME 10 invokes the callback associated with thecontrol.

Some controls allow you to define more than one callback, dependingon how the user interacts with the control. For example, aList controlcan have a callback that is invoked whenever the user selects a newitem. The control also allows you to define a callback that is invokedwhenever the user double-clicks on an item in the list.

You must define the callbacks associated with a control when youcreate the dialog descriptor. When you define each callback, you mustalso specify its type. There are several varieties of callbacks, includingUNIX shell scripts, C programs, and IDL-defined methods. You canfind a full discussion of each type of callback in theDesktop ServicesManual.

The Tivoli/Phone application uses two kinds of callbacks: IDL-stylecallbacks and gadget library callbacks. An IDL-style callback issimply an IDL operation that is registered as a callback. IDL-stylecallbacks are generally used when the user interface needs to access anoperation directly on the underlying object. Gadget library callbacksare C functions that use the object-oriented TME 10 ADE gadgetlibrary to manipulate controls on a dialog or window.

Page 202: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The Gadget Library

7–12 Version 3.6

The Gadget LibraryGadget library callbacks are the primary mechanism an applicationuses to interact with its dialogs and windows. The gadget librarymodels each type of dialog control as a lightweight object. Anapplication acts on a gadget object (and by extension the control itrepresents) through the operations that the object supports. Forexample, to make aButton control insensitive, you could invoke theset_sensitive operation on theglButton gadget object that representsthe button.

void toggle_button(glButton *a_button){ glText_set_sensitive(a_button, FALSE);}

The naming convention for a gadget library operation isglType_operation, whereType is the type of control andoperation isthe name of the operation. The first parameter of a gadget libraryoperation is always the gadget object on which the operation is to run.

Page 203: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The Gadget Library

Application Development with TME 10 ADE 7–13

Creating an A

pplicationU

ser Interface

The Gadget HierarchyThe objects in the gadget library form a class hierarchy, where eachtype of gadget object is derived from another, more basic type.

The set of operations that a gadget object supports depends on the typeof control it represents, although objects that derive from a commonparent share some common set of operations. Because all objects in thelibrary derive fromglGadget, they all support certain basicoperations, such asget_title andset_sensitive. The library enforcesstrict typing, so the object passed to the operation must match (orderive from) the type given in the operation name.

Gadget Library Hierarchy

glBase glDialog

glGadget glButton glCmdButton

glChooser glChoice

glList

glCollection

glGroup

glMenu

glMessage glText

glPage

glSeparator

glSwitch

glTable

glTableHdr glTableColumn

glTableRow

Page 204: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The Gadget Library

7–14 Version 3.6

The Dialog Gadget ObjectWhen an application loads a dialog or window, it obtains aglDialogobject for the dialog. Your application can manipulate the dialog’sattributes with this object, or use it to obtain gadget objects for thedialog’s controls.

TheglDialog object supports an operation calledfind_gadget, whichlocates a named control and returns a gadget object for the control. Theapplication can use the gadget object to manipulate the control. We canextend ourtoggle_button example so that it can find any namedcontrol on the dialog and make it insensitive.

void toggle_control(glDialog *dialog, const char *path){ glGadget *control;

control = glDialog_find_gadget(dialog, path);

glGadget_set_sensitive(control, FALSE);}

The previous version took aglButton control and called theglButton_set_sensitive operation to turn it off. Since our new versiondoes not know what type of control it manipulating, we use theglGadget version of the operation. All gadget object classes derivefrom glGadget, so this function works with any type of gadget object.

Gadget Library CallbacksNow that you have had an introduction to the gadget library, we canreturn to the topic of gadget library callbacks. There are two sides to acallback: its invocation from within a dialog and its implementation inthe user interface program.

Page 205: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The Gadget Library

Application Development with TME 10 ADE 7–15

Creating an A

pplicationU

ser Interface

A gadget library invocation has the following format:

All gadget library callbacks are invoked in the context of some control.TME 10 automatically passes the gadget object that represents thecontrol as the first argument of the callback. Usually the context is thecontrol with which the callback is associated; however, you can use thedialog andcontrol parameters to invoke the callback in a differentcontext. The context parameters are optional; if you omit them, thecallback runs in the context of its native control.

Why would you want to invoke a callback in a different controlcontext? Consider a list control that has a button to remove items.

TheButton control has a callback (call itRemoveItem) associatedwith it whose purpose is to remove the selected item from the listcontrol. In this case, the native context for the callback is thebuttoncontrol. However, the callback is really meant to operate on the listcontrol, not the button. We can use the context parameters to changethe context like so:

RemoveItem&.:node_list($node_list);

callback&[ dialog]:[control](args, ...);

callback

control

name

context

Page 206: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The Gadget Library

7–16 Version 3.6

The example invokes theRemoveItem callback in the context of thenode_list control on the current dialog (the period in the dialog fieldmeans the current dialog).

On the implementation side of a gadget library callback, you mustregister the callback and implement it. Unlike other kinds of callbacks,you must explicitly register gadget library callbacks at run-time beforeyou use them. Most applications define their gadget library callbacksduring the start-up phase of the user interface method. Each callbackdeclaration has several parts.

TheType part of the name defines the gadget object class associatedwith the callback. Every gadget library callback is invoked in thecontext of an object. TME 10 automatically passes the context objectas the first argument to the callback.

Then part of the name is the number of arguments that the callbackaccepts. In the example above, the callback accepts three arguments.The argument count in the callback declaration doesnot include thegadget object parameter that TME 10 automatically provides.

The arguments of the callback declaration define the callback’s publicand private names. The public name is the name used when specifyingthe callback in a dialog descriptor. The private name is the name of thecallback function name. Of course, the two names can be the same; thedual naming convention is simply to provide a measure of flexibility.

The implementation of a callback function is a regular C function. Itsfirst argument, as mentioned before must be the gadget object in whosecontext the callback is invoked. Thechange_profile_label callbackfunction is shown below. The callback changes the label of a profileand updates the subscription path that appears on the propertieswindow.

glType_define_n(public_name, private_name);

gadget

number of

type

arguments

Page 207: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The Gadget Library

Application Development with TME 10 ADE 7–17

Creating an A

pplicationU

ser Interface

1 void change_profile_label(glButton *b,

2 const cbarg_t new_label)

3 {

4 glDialog *dialog;

5 Object self;

6 Environment ev = {0};

7 char *context;

8

9 Try {

10 /* Get the object ID of the profile object */

11 self = tmf_locate_self();

12 ml_ex_attach_Object_reference(self);

13

14 t_SysAdmin_PolicyDrivenBase__set_label(self,

15 &ev, Trans_revocable,

16 (char *)new_label);

17 }

18 /*

19 * Set label throws an exception if the new label

20 * is the same as the old. Ignore it.

21 */

22 CatchAll() {

23 /* EMPTY */

24 }

25 EndTry;

26

27 /* Change the subscription path to reflect the

28 * name change

29 */

30 dialog = glButton_get_dialog(b);

31

32 context = ccms_get_current_sub_path(self);

33 set_subscription_path(dialog, context);

34 mg_free(context);

35 }

The callback function accepts two arguments: the obligatory gadgetobject and one data argument,new_label. In this case, the callback isinvoked in the context of aButton control, so the first argument is aglButton gadget object.

The second argument,new_label, contains the new profile label. Theargument is of typecbarg_t and is declared constant. In fact, all data

Page 208: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Launching a Dialog

7–18 Version 3.6

arguments passed to a gadget library callback areconst cbarg_t. Thecbarg_t data type is a typedef forchar * , however, so you can treatthem as strings. This is important to remember, because you mustconvert numerical arguments from strings to numbers before usingthem.

The body of thechange_profile_label function calls the_set_labelmethod on the profile object to change its label. It also updates thesubscription path that appears on the properties window to reflect thename change. To call theset_subscription_path function, thecallback must get the gadget object of the dialog. The callback obtainstheglDialog object from theglButton gadget, using theget_dialogoperation. Theget_dialog operation, which is supported by all gadgetobjects, returns theglDialog object of the dialog where the controlresides.

Launching a DialogAs you read at the beginning of this chapter, the starting point for theTivoli/Phone application’s user interface is the profile propertieswindow. This window is launched through a Tivoli/Phone icon’spop-up menu.

Page 209: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Launching a Dialog

Application Development with TME 10 ADE 7–19

Creating an A

pplicationU

ser Interface

Tivoli/Phone has only one entry point to the user interface, but anapplication can potentially have many starting points. Each entry pointusually appears on the icon pop-up menu.

The application user interface is tied to the object icon through anIDL-defined method. For Tivoli/Phone, the method is calledui_phone_props. The operation is defined as part of theTPL::PhoneListGUI interface. Theui_phone_props methodprepares the user interface and displays the Tivoli/Phone profileproperties window.

Because theui_phone_props operation is invoked from within adialog, it must conform to a certain signature format. The IDLsignature ofui_phone_props is shown below.

void ui_phone_props(in TMF_Types::StringList argv, in TMF_Types::StringList env, out TMF_Types::OctetList commands);

Parameter Description

argv Sequence of callback arguments (the first element isalways the method name)

env Sequence of desktop environment variables

commands List of desktop commands for the TME 10 UI server(output parameter)

Page 210: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Launching a Dialog

7–20 Version 3.6

Theenv parameter is aStringList sequence that contains environmentvariables for the method. The TME 10 desktop passes the followingenvironment variables:

■ WD_DESKTOP_OID — The object reference of theTMF_UI::Desktop object associated with the desktop thatinvoked the callback.

■ WD_DESKTOP_PID — The process ID of the desktop serverthat invoked the callback.

■ WD_OCO_OID — The object reference of theAdministratorConfiguration object that represents the principal who invokedthe callback.

Thecommands output parameter is used to return desktop commandsto the TME 10 desktop. The Tivoli/Phone application does not use thismechanism for sending desktop commands.

Tivoli/Phone implements its UI method server as a threaded daemonserver. The threaded daemon allows multiple users to view a profile’sdata simultaneously and to share display data between instances of theprofile dialogs. The program specification for the UI method server isshown below.1 program Phone_ui_prog1 timeout = 180 for

2 imp_TPL::PhoneListProfile {

3 executes {

4 ui_phone_props

5 } threaded daemon;

6

7 //

8 // Define the functions called whenever the

9 // method starts.

10 //

11 startup {

12 "phone_gui_init"

13 };

14 };

The program specification defines a threaded daemon server with atime-out of 180 seconds. The start-up function,phone_gui_init,initializes the method server and defines all the gadget librarycallbacks used by the application interface.

Page 211: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Launching a Dialog

Application Development with TME 10 ADE 7–21

Creating an A

pplicationU

ser Interface

The code below shows a basic implementation for theui_phone_props method. This implementation posts the applicationdialog window, presents it to the user, and waits to be dismissed. Inlater sections of this chapter, we will expand this implementation touse the TME 10 ADE table manager to display and manipulate profiledata with aTable gadget.1 void t_imp_TPL_PhoneListProfile_ui_phone_props(

2 TPL_PhoneListProfile profile,

3 Environment *_ev,

4 transaction _transaction,

5 TMF_Types_StringList* argv,

6 TMF_Types_StringList* env,

7 TMF_Types_OctetList* commands)

8 {

9 Object profile_org;

10 char dialog_name[30];

11 char *profile_org_name, *profile_name, *context;

12 glDialog *props_dialog;

13 Environment ev = {0};

14 ml_t *mh = ml_create();

15

16 /* Create a unique internal name for the dialog */

17 sprintf(dialog_name, "phone_props:%d",

18 ++props_dialog_count);

19

20 /* Get values to bind to the dialog's variables */

21 profile_name =

22 _t_TPL_PhoneListProfile__get_label(profile,

23 &ev);

24 ml_attach_ORB_generic(mh, &profile_name,

25 TC_string);

26

27 profile_org =

28 _t_TPL_PhoneListProfile__get_profile_organizer(

29 profile, &ev);

30 ml_attach_Object_reference(mh, profile_org);

31

32 profile_org_name =

33 t_SysAdmin_PolicyDrivenBase__get_label(

34 profile_org, &ev, Trans_revocable);

35 ml_attach_ORB_generic(mh, &profile_org_name,

Page 212: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Launching a Dialog

7–22 Version 3.6

36 TC_string);

37

38 context = ccms_get_current_sub_path(profile);

39 ml_attach_addr(mh, context);

40

41 /* Load the properties dialog */

42 props_dialog = glDialog_load_env(env,

43 dialog_name, PROPS_DIALOG_NAME,

44 "PROFILE_NAME", profile_name,

45 "PROF_ORG_NAME", profile_org_name,

46 "CONTEXT_PATH", context,

47 NULL);

48

49 ...

50

51 /* Free the dialog parameters */

52 ml_destroy(mh);

53

54 /* Set the value of the dialog gadget that

55 * shows the number of records in the profile */

56 set_num_entries(props_dialog,

57 tds_table_get_cache_size(CACHE_NAME));

58

59 /* Present the dialog and wait to be dismissed */

60 glDialog_run(props_dialog);

61

62 /* Zero out the method return buffer */

63 seq_init((sequence_t *)commands);

64 }

The entry point for an application’s user interface is called itstop-leveldialog. The top-level dialog provides a common parent dialog for allsubsequent application dialogs. To post a top-level dialog, anapplication calls theglDialog_load_env operation. The operationloads an instance of a given dialog and returns aglDialog gadgetobject for the dialog instance.

A dialog has two names: its name on the presentation object and aninstance name. TME 10 requires that dialogs in the same gadgetcontext (process space) have unique instance names. This is not aproblem for methods that run as per method servers or as non-threadeddaemons. Since theui_phone_props method is a threaded daemon

Page 213: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Launching a Dialog

Application Development with TME 10 ADE 7–23

Creating an A

pplicationU

ser Interface

method, there can potentially be several copies of the profile propertieswindow open for a single profile. To avoid name clashes, theui_phone_props implementation constructs a unique instance namefor each copy of the window.

Dialogs can also have parameters. Dialog parameters usually provideseed values for various controls on the dialog. When you load a dialog,you must provide values for all the parameters expected by a dialog.In theui_phone_props implementation, the properties windowexpects three parameters:

■ PROFILE_NAME —The label of the profile object.

■ PROF_ORG_NAME—The label of the profile manager orendpoint that contains the profile.

■ CONTEXT_PATH —The subscription hierarchy through whichthe current profile was received.

If you do not supply values for all parameters that a dialog expects, theglDialog_load_env operation throws an exception.

TheglDialog_run operation makes a posted dialog visible to the user.

Page 214: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

7–24 Version 3.6

TheglDialog_run operation blocks until the user dismisses the dialog.The operation creates amodal dialog; the dialog that invoked thelaunch method remains busy until the user closes the dialog. If youwant to post a non-modal dialog, you can use theglDialog_presentoperation. This operation makes the dialog visible and returns withoutwaiting for the user to dismiss the dialog.

Managing Tabular DataSince a profile object contains records of data that comprise somenumber of fields, profile data is usually represented in tabular form.The Tivoli control set includes aTable control, which provides a wayto organize and display tabular data.

Writing code to manage, update, and manipulate the data in aTablecontrol can represent a large portion of the effort to develop a profileobject’s user interface. The user interface must be able to manipulaterows and columns in the table based on a wide variety of user input.For example, the Tivoli/Phone application allows the user to add, edit,and delete entries in the table, and even change the order of the rows

Page 215: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

Application Development with TME 10 ADE 7–25

Creating an A

pplicationU

ser Interface

and columns. The code to perform these actions is not complicated,just voluminous and time-consuming to write.

To simplify the development of table-based user interfaces, TME 10ADE provides a table manager library. Given a cache of applicationdata and a list of columns, the table manager handles the routine choresof displaying and manipulating entries in a table control.

To use the table manager, you must do the following in theapplication’s dialog descriptor:

1. Define aTable control.

2. Set theExpose attribute of theTable control to use the tablemanager’s expose callback. The TME UI server invokes theexpose callback whenever it needs to paint one or more rows inthe table. See “The Expose Mechanism” on page 7-38 for adetailed explanation of how the expose mechanism work.

To support the table manager in your application methods andcallbacks, you must do the following:

1. Create a display cache that contains your application data to bedisplayed.

2. Register theTable control with the table manager.

3. Define the columns that you want to appear in the table.

4. You must also link your GUI method program with thelibtablelibrary. The prototypes and data types used by the table managercan be found in the<tivoli/tds_table.h> include file.

Page 216: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

7–26 Version 3.6

The Display CacheTo use the table manager, an application creates a named cache of dataand delegates it to the table manager. The cache should contain thedata necessary to create the text of each cell in the table. For example,the Tivoli/Phone user interface stores aPhoneEntryInfo structure foreach record in its display cache.

Multiple dialogs can use the same cache, which allows an applicationto support concurrent viewing and editing of the same data. Changesmade to the display cache by one copy of the dialog are automaticallyreflected in the other copies.

Users are also free to manipulate the table view—such as changing therow order—independently of the other copies. The table managermaintains a list for each copy of the dialog that maps row numbers toentries in the display cache. So, cache entryelem1 might be row 1 inone dialog, but row 150 in another. When your application changes an

elemn

elem1

.

.

.

.

.

elem2

elem3

phone_cache

Page 217: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

Application Development with TME 10 ADE 7–27

Creating an A

pplicationU

ser Interface

entry in the display cache, the table manager updates the correct rowon all tables that use the cache.

Creating a Display Cache

To create a display cache with the table manager, you application mustsupply the following information:

■ A name for the cache

■ The size of each cache element

■ A pointer to a function that supplies the cached data

Since the table manager simply manages the display cache, yourapplication must supply the data that goes in the cache. The cachesupplier function must have the following signature:

tmf_boolean func(void *, sequence_t *);

The first argument to the function provides a way for the applicationto pass data to the supplier function. Tivoli/Phone, for example, usesthis argument to pass the object reference of the profile object to thecache supplier. The second argument is a pointer to the cache sequenceitself.

Thetds_table_load_cache library function creates a display cache forthe table manager. Thetds_table_load_cache call from theTivoli/Phone application is shown below.1 void t_imp_TPL_PhoneListProfile_ui_phone_props(

2 TPL_PhoneListProfile profile,

3 Environment *_ev,

4 transaction _transaction,

5 TMF_Types_StringList* argv,

6 TMF_Types_StringList* env,

7 TMF_Types_OctetList* commands)

8 {

9 Object profile_org;

10 char dialog_name[30];

11 char *profile_org_name, *profile_name, *context;

12 glDialog *props_dialog;

13 Environment ev = {0};

14 ml_t *mh = ml_create();

15 TableMgr_CacheResultList results;

Page 218: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

7–28 Version 3.6

16

17 ...

18

19 /* Make sure the cache isn’t already loaded */

20 if (!tds_table_is_cache_loaded(CACHE_NAME)) {

21 SupplierArgs args;

22

23 /* Set up the args to be passed to the supplier

24 * function. */

25 args.obj = profile;

26

27 /*

28 * Load the cache of application data. The

29 * "fill_gui_cache" function (arg 3) supplies

30 * the app data for the table manager.

31 */

32 tds_table_load_cache("phone_cache",

33 sizeof(TPL_PhoneEntryInfo),

34 fill_gui_cache, &args,

35 NULL, NULL, &results);

36 }

37

38 /* Load the dialog */

39 ...

40

41 }

The application creates a cache calledphone_cache and indicates thatthe element size is the size of aPhoneEntryInfo data structure. Theapplication also definesfill_gui_cache as the application’s cachesupplier function. The supplier function must have the followingsignature:

tmf_boolean supplier_func( void *params, sequence_t *cache, TableMgr_CacheResultList *results)

Theparams parameter contains any data that thefill_gui_cachefunction needs to complete the operation. The application defines thecontents of this parameter, which is passed to the supplier functionthrough the call totds_table_load_cache. In theui_phone_propsmethod, theparams parameter points to a structure of type

Page 219: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

Application Development with TME 10 ADE 7–29

Creating an A

pplicationU

ser Interface

SupplierArgs, which contains the object reference of the currentprofile object.

The results parameter provides a way for the supplier function toreturn any errors encountered to the method that calledtds_table_load_cache. The parameter is a sequence whose elementshave the following IDL definition:

struct CacheResult { string row; any ex;}

The tds_table_load_cache function does not look at theresultssequence; it simply passes it back to the caller. How your applicationuses this sequence is up to you. The Tivoli/Phone application does notmake use of this feature.

The Tivoli/Phone supplier function,fill_gui_cache, uses thePhoneListProfile::get_all_entries method to retrieve the profile’srecords and put them into the cache sequence. Ifget_all_entriesreturns an iterator (because there are a large number of records),fill_gui_cache uses the iterator to retrieve the data in chunks.1 tmf_boolean fill_gui_cache(

2 void *params,

3 sequence_t *cache

4 TableMgr_CacheResultList *results)

5 {

6 TPL_PhoneEntryInfoList more_entries;

7 SupplierArgs *args;

8 Object profile, iterator;

9 Environment ev = {0};

10 tmf_boolean more;

11

12 /*

13 * Pull the profile object reference out

14 * of the parameter passed to us.

15 */

16 args = (SupplierArgs *)params;

17 profile = args->obj;

18

19 Try {

20

Page 220: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

7–30 Version 3.6

21 /*

22 * Get all the entries in the profile

23 * and put them in the display cache

24 * sequence.

25 */

26 t_TPL_PhoneListProfile_get_all_entries(

27 profile,

28 &ev,

29 Trans_sub,

30 (TPL_PhoneEntryInfoList *)cache,

31 &iterator);

32

33 /*

34 * If there was an iterator, get the

35 * rest of the entries.

36 */

37 more = !Object_is_nil(iterator, &ev);

38

39 while (more) {

40 seq_init((sequence_t *)&more_entries);

41

42 more = t_TPL_PhoneListProfile_next_entries(

43 iterator,

44 &ev,

45 Trans_revocable,

46 100,

47 &more_entries);

48

49 seq_append(cache,

50 (sequence_t *)&more_entries,

51 sizeof(TPL_PhoneEntryInfo));

52 }

53 }

54 CatchAll() {

55 ExPhoneError *ex =

56 (ExPhoneError *)ExPhoneErrorNew(

57 phone_msgs,

58 gui_cache_failed);

59 ContextThrow(ex->type_name, ex);

60 }

61 EndTry;

62

Page 221: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

Application Development with TME 10 ADE 7–31

Creating an A

pplicationU

ser Interface

63 return(FALSE);

64 }

Freeing a Display Cache

When you create a display cache with the table manager, yourapplication allocates a block of memory (sequence) and turns it overto the manager. When the application frees the cache, the tablemanager turns the memory over to the application to be freed. Theapplication must register a function that the table manager calls whenthe cache is freed. The function is responsible for releasing thememory allocated for the cache.

tds_table_set_free("phone_cache", free_gui_cache);

The Tivoli/Phone application’s cache release function is calledfree_gui_cache. Since thePhoneEntryInfoList data type is definedin IDL and the memory was originally allocated by the ORB (as theoutput of a method call), Tivoli/Phone uses the ORB to free it.1 void free_gui_cache(sequence_t *cache_data)

2 {

3 tmf_free_generic(cache_data,

4 TC_PhoneEntryInfoList);

5 }

Thefree_gui_cache function callstmf_free_generic and passes it thecache and the data type (TC_PhoneEntryInfoList ). The ORB freesthe cache data.

Other Cache-related Operations

The table below shows some of the cache-related functions that thetable manager library supports.

Function Purpose

tds_table_get_cache_size Returns the size of a cache element

tds_table_is_cache_loaded ReturnsTRUE if the named cachealready exists

tds_table_refresh_cache Dumps the contents of a named cacheand reloads

Page 222: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

7–32 Version 3.6

Registering a TableThe tds_table_register_table function registers aTable control withthe table manager. From the time you register your table — until youunregister the table withtds_table_exit — the table manager isresponsible for populating the table with data and managing its rowsand columns.

When you calltds_table_register_table, you must specify thefollowing data:

■ The gadget object for the dialog that contains the table.

■ The name of theTable control.

■ The name of the cache to associate with the table.

■ A pointer to a function that can return the text of a cell in thetable.

■ A pointer to a function that can return the name of a glyph. Aglyph is a small bitmap that can appear in the header of a row.Glyphs are used to indicate the status of a record (such as“locked”).

The table manager expose callback uses the latter two items on the listwhen it paints the table rows. See “The Expose Mechanism” onpage 7-38 for more information on the expose mechanism.

The code fragment below shows where thetds_table_register_tablecall fits into theui_phone_props method implementation. Since thecall requires the name of a valid cache and a pointer to aglDialogobject, the call totds_table_register_table must come after the dialoghas been posted.1 void t_imp_TPL_PhoneListProfile_ui_phone_props(

2 TPL_PhoneListProfile profile,

3 Environment *_ev,

4 transaction _transaction,

5 TMF_Types_StringList* argv,

6 TMF_Types_StringList* env,

7 TMF_Types_OctetList* commands)

8 {

9 Object profile_org;

10 char dialog_name[30];

Page 223: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

Application Development with TME 10 ADE 7–33

Creating an A

pplicationU

ser Interface

11 char *profile_org_name, *profile_name, *context;

12 glDialog *props_dialog;

13 Environment ev = {0};

14 ml_t *mh = ml_create();

15

16 /* Make sure the cache isn’t already loaded */

17 if (!tds_table_is_cache_loaded(CACHE_NAME)) {

18 SupplierArgs args;

19

20 /* Set up the args to be passed to the supplier

21 * function. */

22 args.obj = profile;

23

24 /*

25 * Load the cache of application data. The

26 * "fill_gui_cache" function (arg 3) supplies

27 * the app data for the table manager.

28 */

29 tds_table_load_cache("phone_cache",

30 sizeof(TPL_PhoneEntryInfo),

31 fill_gui_cache, &args,

32 NULL, NULL, &results);

33 }

34

35 ...

36

37 /* Load the properties dialog */

38 props_dialog = glDialog_load_env(env,

39 dialog_name, PROPS_DIALOG_NAME,

40 "PROFILE_NAME", profile_name,

41 "PROF_ORG_NAME", profile_org_name,

42 "CONTEXT_PATH", context,

43 NULL);

44

45 /* Register the table with the table manager */

46 tds_table_register_table(props_dialog,

47 TABLE_NAME,

48 "phone_cache",

49 get_cell_data,

50 set_glyph);

51

52 /* Register the table to use the libccms_gui

Page 224: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

7–34 Version 3.6

53 * CCMS library dialogs */

54 ...

55

56 /* Present the dialog and wait to be dismissed */

57 glDialog_run(props_dialog);

58 }

After you register aTable control, subsequent calls to table managerfunctions require the dialog gadget object and the name of the tablegadget.

Defining Table ColumnsAfter registering the table control, your application must define thecolumns that are to appear in the table. In the Tivoli/Phone application,there are always 10 columns plus columns for any custom attributesadded with TME 10 AEF. Theui_phone_props method calculates thenumber of display columns and uses thetds_table_add_columnfunction to define them.1 static void init_column_data(glDialog *dialog,

2 const char *table_name)

3 {

4 any bogus_any = {0, 0};

5 TPL_PhoneEntryInfo *ep;

6 TPL_AEFAttr *aef_attr;

7 int num_aef_attrs, num_cols;

8 ColumnInfo column;

9 int i;

10

11 /*

12 * Figure out how many columns there are.

13 */

14 ep = tds_table_get_row(dialog, table_name, 0);

15 if (ep != NULL) {

16 num_aef_attrs = seq_len(

17 (sequence_t *)&(ep->aef_attrs));

18 num_cols = NUM_FIXED_COLS + num_aef_attrs;

19 }

20 /* If there aren't any records, assume the

21 * standard number

22 */

23 else {

Page 225: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

Application Development with TME 10 ADE 7–35

Creating an A

pplicationU

ser Interface

24 num_cols = NUM_FIXED_COLS;

25 num_aef_attrs = 0;

26 }

To define a new column for a table, the application must set up aColumnInfo data structure and pass it to thetds_table_add_columnfunction. TheColumnInfo structure defines the characteristics of thecolumn, including:

■ The internal name of the column

■ The column title (a language-dependent message)

■ The default width of the column, in text rows

■ A flag indicating whether the column is initially visible,invisible, or permanently invisible

■ A pointer to a function that compares two cells of the samecolumn (used to sort by column)

Theui_phone_props method sets up aColumnInfo structure for itsstandard columns and callstds_table_add_column to define them.27 column.name = NAME_COL;

28 column.title = tmfMsgNew(phone_msgs,

29 name_tbl_hdr, bogus_any);

30 column.width = 20;

31 column.visible = COL_INVISIBLE;

32 column.sort_func = cmp_fields;

33 tds_table_add_column(dialog, table_name, &column);

The fragment above defines the name column. In this case, the columnis 20 characters wide, and is initially invisible when the table isdisplayed (invisible columns can subsequently be made visible). Thecomparison function associated with the column is calledcmp_fields.The other Tivoli/Phone columns are defined in a similar fashion to thename column.34

35 /* Phone column */

36 column.name = PHONE_COL;

37 column.title = tmfMsgNew(phone_msgs,

38 phone_tbl_hdr, bogus_any);

39 column.width = 15;

40 column.visible = VISIBLE;

41 column.sort_func = cmp_fields;

Page 226: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

7–36 Version 3.6

42 tds_table_add_column(dialog, table_name, &column);

43

44 /* Owner Column */

45 column.name = OWNER_COL;

46 column.title = tmfMsgNew(phone_msgs,

47 owner_tbl_hdr, bogus_any);

48 column.width = 10;

49 column.sort_func = cmp_fields;

50 tds_table_add_column(dialog, table_name, &column);

51

52 /* "Type" Column */

53 column.name = TYPE_COL;

54 column.title = tmfMsgNew(phone_msgs,

55 type_tbl_hdr, bogus_any);

56 column.width = 10;

57 column.sort_func = cmp_fields;

58 tds_table_add_column(dialog, table_name, &column);

59

60 /* Define the remaining columns */

61 ...

When the method has defined the 10 regular columns, it createscolumns for any attributes that have been added to the profile withTME 10 AEF. Since the method does not have a locale-dependent titleto give to the column, it uses the attribute name as the title.62 /*

63 * Create columns for the AEF attributes.

64 * We will just use the

65 * attribute name as the column title.

66 */

67 for (i = 0; i < num_aef_attrs; i++) {

68 char colname[20];

69

70 aef_attr = (TPL_AEFAttr *)seq_get(

71 (sequence_t *)&(ep->aef_attrs), i,

72 sizeof(TPL_AEFAttr));

73

74 sprintf(colname, "%s%d", AEF_COL_PREFIX, i);

75 column.name = mg_strdup(colname);

76 bogus_any._value = &aef_attr->name;

77 bogus_any._type = TC_string;

78 column.title = tmfMsgNew(phone_msgs,

Page 227: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

Application Development with TME 10 ADE 7–37

Creating an A

pplicationU

ser Interface

79 aef_tbl_hdr, bogus_any);

80 column.width = 20;

81 column.sort_func = cmp_fields;

82 tds_table_add_column(dialog,

83 table_name, &column);

84 }

85 ...

86 }

After a column has been defined, the application can use the internalcolumn name to refer to the column. For example, thetds_table_set_sort_column sets the column by which the table issorted. The function takes the internal name of a column.

tds_table_set_sort_column(dialog, table_name, NAME_COL, TRUE);

The table below lists the table manager functions that manipulate thecolumns in a table.

Function Purpose

tds_table_add_column Defines a column

tds_table_remove_column Removes a column

tds_table_set_key_column Sets the column that appears asthe row title

tds_table_set_sort_column Sets the column by which rowsin a table are sorted

tds_table_is_column_visible ReturnsTRUE, if the columnis currently visible

tds_table_set_column_visible Controls whether a column isvisible to the user

tds_table_set_column_order Sets the left-to-right order inwhich columns are displayed

tds_table_get_column_order Retrieves the column order

tds_table_set_column_edit Defines a column-editingcallback for a column

Page 228: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

7–38 Version 3.6

The Expose MechanismTo prevent performance problems with large tables, TME 10 does notcreate all the rows of aTable control at once. Instead, it populates onlythe rows that can initially be seen by a user. When the user uses thescroll bar to browse through the table, TME 10 requests more rowsfrom the application. This process is known as theexpose mechanism.

EveryTable control supports an attribute calledExpose, whichcontains the name of a callback. TME 10 invokes theExpose attributewhenever it displays a new set of rows in the table. TME 10 passes thecallback a range of rows that it needs to be populated. The callback isresponsible for supplying the data for the new rows.

The table manager includes a standard expose callback calledtds_table_expose_cb. If you are using the table manager library tomanage your table, you should set theExpose attribute of theTablecontrol totds_table_expose_cb.

Since the table manager has no implicit knowledge of what data isstored in the display cache (except the element size), the managercannot populate the rows of a table without the aid of the application.To perform the mapping between application data and cell text, thetable manager calls the function you specified when you registered thetable.

If you recall the discussion oftds_table_register_table, one of theparameters you specify is a function that can transform an element of

tds_table_toggle_column_edit Enables/disablescolumn-editing for a column

tds_table_is_column_editable ReturnsTRUE if the columnallows column editing

tds_table_set_column_hdr_height Sets the height of the tablecolumn headers

Function Purpose

Page 229: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

Application Development with TME 10 ADE 7–39

Creating an A

pplicationU

ser Interface

the display cache into the text for a cell. The function must have thefollowing signature:

char *cell_func(const char *column_name, void *data);

Thecolumn_name parameter is the name of a column created withtds_table_add_column. Thedata parameter is an element of datafrom the display cache. The application function uses the columnname to determine which cell it must populate.

The cell text function for Tivoli/Phone is calledget_cell_data. Thefunction examines the column name and returns the appropriate fieldof thePhoneEntryInfo structure.1 char *get_cell_data(const char *column_name,

2 void *data)

3 {

4 char *retval;

5 TPL_PhoneEntryInfo *ep;

6

7 ep = (TPL_PhoneEntryInfo *)data;

8

9 if (strcmp(column_name, NAME_COL) == 0) {

10 retval = (ep->name != NULL) ? ep->name : "";

11 }

12 else if (strcmp(column_name, PHONE_COL) == 0) {

13 retval = (ep->phone != NULL) ? ep->phone : "";

14 }

15

16 ...

17

18 else if (strcmp(column_name, COMMENT_COL) == 0) {

19 retval = (ep->comment != NULL) ? ep->comment

20 : "";

21 }

22 else {

23 int col_num;

24 TPL_AEFAttr *aef_attr;

25

26 sscanf(column_name, "AEF_ATTR_%d", &col_num);

27

28 aef_attr = (TPL_AEFAttr *)seq_get(

Page 230: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

7–40 Version 3.6

29 (sequence_t *)&ep->aef_attrs,

30 col_num, sizeof(TPL_AEFAttr));

31 retval = (char *)aef_attr->value;

32 }

33

34 return(retval);

35 }

If the column name does not match one of the standard Tivoli/Phonecolumns,get_cell_data assumes that the column represents anattribute added with TME 10 AEF. The function uses an index encodedin the name of the column to determine which custom attribute is beingrequested. Another, more general, way of accomplishing this would beto include the attribute name in the column name.

You might have noticed that the return type of the cell text callback ischar * . This means that if your application stores any of its cell dataas locale-independent messages, your cell text callback must bind themessage to text before returning it to the table manager.

Manipulating Table RowsAfter you have gone to the trouble of registering your table andpopulating it with rows, manipulating the rows is comparatively easy.To add a row to a table, for example, you simply call thetds_table_add_row function and pass it the new element for thedisplay cache. The table manager updates the cache and inserts a newrow at the appropriate location on all tables that share the cache, takinginto account how the rows in each table are sorted.

tds_table_add_row(dialog, table_name, new_elem);

Changing an existing a row is also fairly simple. There are two waysto change a row:tds_table_change_row andtds_table_change_row_by_key. Thetds_table_change_rowfunction takes a row number in a given table and updates the cacheentry associated with the row. The example below updates row 10 inthe given table with thenew_elem data item.

tds_table_change_row(dialog, table_name, new_elem, 10);

Page 231: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

Application Development with TME 10 ADE 7–41

Creating an A

pplicationU

ser Interface

The tds_table_change_row_by_key function allows you to update arow when you are not sure where it resides in the table. Instead of arow number, the function takes a target key and a pointer to a functionthat can return a unique key for each record. The following codefragment calls the shows thetds_table_change_row_by_keyfunction in action.1 void change_entry_cb()

2 {

3 /* Get values from edit dialog */

4 ...

5

6 /* Change the profile record */

7 Try {

8 t_TPL_PhoneListProfile_modify_phone_entry(

9 profile, &ev,

10 Trans_top, key, entry);

11 }

12 CatchAll() {

13 clear_edit_lock(parent, key);

14 ReThrow;

15 }

16 EndTry;

17

18 entry->flags = 0;

19

20 /* Notify the table manager of the change */

21 tds_table_change_row_by_key(

22 parent, table_name, entry,

23 key, make_record_key);

24 }

The callback invokes PhoneListProfile::modify_phone_entry tochange an entry in the database, then callstds_table_change_row_by_key to update the table. The applicationuses themake_record_key function as the key generator, since itreturns a profile record key given aPhoneEntryInfo structure.

Page 232: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Managing Tabular Data

7–42 Version 3.6

The table below lists the functions included in the table managerlibrary to manipulate the rows in aTable control.

Function Purpose

tds_table_add_row Adds a row to a display cache

tds_table_get_selected Returns a list of the currentlyselected rows

tds_table_change_row Updates the cache entryassociated with a given row

tds_table_change_row_by_key Updates the cache entry thathas a given unique key

tds_table_get_row Returns the cache entryassociated with a given row

tds_table_get_row_by_key Returns the cache entry that hasa given unique key

tds_table_remove_row Removes a row from thedisplay cache

tds_table_remove_rows Removes a range of rows

tds_table_select_all Selects all rows in the table

tds_table_deselect_all Clears the highlight from thecurrently selected rows

tds_table_show_selected Restricts the displayed rows tothe current selection

tds_table_show_all Shows all rows in the table

tds_table_set_row_hdr_width Sets the width of the rowheader column

tds_table_redraw_rows Refreshes all rows in the table

tds_table_redraw_rows_all_tables Refreshes all rows on all tablesthat use the same cache

Page 233: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Using the TME 10 Support Dialogs

Application Development with TME 10 ADE 7–43

Creating an A

pplicationU

ser Interface

Using the TME 10 Support DialogsTheTivoli User Interface Style Guide defines a standard user interfacefor profile applications. As part of this interface standard, the guidedefines numerous dialogs that perform operations common to allprofile applications. These include:

■ Sorting rows and columns

■ Distributing a profile

■ Navigating between copies of a profile

■ Moving and copying records

■ Setting policy for a profile

■ Validating policy

TME 10 ADE provides a library that implements these standarddialogs. The library contains gadget library callbacks that you caninclude in your application’s dialogs.

Note: The library callbacks make extensive use of thelibtablelibrary, so you must use the table manager if you want to usethe standard dialogs.

To use the standard profile dialogs, you must do the following:

1. Initialize the gadget library callbacks in the CCMS dialog library.You can do this by callingccms_init_callbacks when yourlaunch method starts.

2. Register your table with CCMS using theccms_register_tablefunction. You must have previously registered the table with thetable manager. When you register your table, you must specifythe name of a profile class and a function that can generate aprofile record key given an element in your display cache.

The code fragment below shows how theui_phone_propsmethod registers to use the standard CCMS dialogs.

1 void t_imp_TPL_PhoneListProfile_ui_phone_props(

2 TPL_PhoneListProfile profile,

3 Environment *_ev,

4 transaction _transaction,

5 TMF_Types_StringList* argv,

Page 234: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Using the TME 10 Support Dialogs

7–44 Version 3.6

6 TMF_Types_StringList* env,

7 TMF_Types_OctetList* commands)

8 {

9 Object profile_org;

10 char dialog_name[30];

11 char *profile_org_name,

12 *profile_name, *context;

13 glDialog *props_dialog;

14 Environment ev = {0};

15 ml_t *mh = ml_create();

16

17 /* Initialize and load the display cache */

18 ...

19

20 /* Load the properties dialog */

21 props_dialog = glDialog_load_env(env,

22 dialog_name, PROPS_DIALOG_NAME,

23 "PROFILE_NAME", profile_name,

24 "PROF_ORG_NAME", profile_org_name,

25 "CONTEXT_PATH", context,

26 NULL);

27

28 /* Register the table with the manager */

29 tds_table_register_table(props_dialog,

30 TABLE_NAME,

31 "phone_cache",

32 get_cell_data,

33 set_glyph);

34

35 /* Register with the CCMS dialog manager */

36 ccms_register_table(props_dialog,

37 TABLE_NAME,

38 PHONE_PROFILE_CLASS,

39 make_record_key);

40

41 ccms_set_bitmap_title(props_dialog,

42 TABLE_NAME,

43 "phone_icon");

44

45 /* Define the table columns */

46 ...

47

Page 235: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Using the TME 10 Support Dialogs

Application Development with TME 10 ADE 7–45

Creating an A

pplicationU

ser Interface

48 /* Present the dialog and wait */

49 glDialog_run(props_dialog);

50 }

3. Link your method server program with thelibccms_gui library.You can find the prototypes and data types used by the tablemanager in the<tivoli/ccms_diag.h> include file.

4. Embed the library’s callbacks in your application’s dialog. Thetable below shows the callbacks and dialogs in the library.

5. Add the TME 10 support dialogs to your presentation object. Todo this, you must change theinitpres command to includeTableMgrGuiDlgs as a parent of your class’s presentationobject.

initpres $imp_phone_CO -class -create \ dialog phone_props $METHODPATH/phone_props.d \

Callback Dialog

ccms_push_cb Distribute Profile

ccms_push_defs_cb Distribute Defaults

ccms_navigate_cb Go To Profile

ccms_pull_cb Get New Copy

ccms_validate_cb Validate Profile

ccms_val_pol_cb Set ValidationPolicies

ccms_def_pol_cb Set Default Policies

ccms_move_rec_cb Move Records

ccms_copy_rec_cb Copy Records

ccms_find_cb Find Records

ccms_sort_recs_cb Sort Records

ccms_sort_attrs_cb Sort Columns

Page 236: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Using the TME 10 Support Dialogs

7–46 Version 3.6

dialog add_dialog $METHODPATH/add_dialog.d \ dialog edit_dialog $METHODPATH/edit_dialog.d \ ... \ parent TableMgrGuiDlgs

In addition to the callbacks, thelibccms_gui library includes severalfunctions that allow you to configure the appearance and behavior ofthe standard dialogs.

Function Purpose

ccms_set_column_policy Sets the type of policy allowed for agiven table column

ccms_set_bitmap_title Sets the bitmap used in the title of thesupport dialogs

ccms_get_bitmap_title Returns the name of the currentbitmap title

ccms_get_current_sub_path Returns the subscription path to agiven profile

Page 237: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Development with TME 10 ADE 8–1

Writing C

lient Program

s

8Writing Client Programs

The majority of this book is aimed at the server side of “client/server.”Although many method implementations act as clients to othermethods, they still exist in the context of a server program. In thischapter, we will discuss how to create a true TME 10 client; astand-alone program whose only access to TME 10 is through clientstubs.

Stand-alone client programs have a variety of uses. For example,suppose you want to create an application that uses TME 10, but doesnot use the TME 10 desktop for its user interface. You can create astand-alone program that implements the user interface in the manneryou choose (Motif, Windows, and so on) that acts as a client to theunderlying TME 10 objects.

Another use for client programs is to provide a non-graphical interfaceto an application in addition to a graphical one. Command line utilities

8

Endpoint Objects as ClientsThe discussion in this chapter applies to server clients, such as theManagedNode object, not toEndpoint clients, such as the LCFendpoint. As there is no GUI on an LCF endpoint, there is also no CLI.On an LCF endpoint, you would use an upcall to provide equivalentfunctionality. For an example of how to provide this functionality on anLCF endpoint, refer to the example application,record_gen,documented inApplication Development for the Lightweight ClientFramework.

Page 238: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Client Program Requirements

8–2 Version 3.6

(also called CLI commands) allow a user to manipulate applicationobjects from workstations that cannot support a TME 10 desktop.Administrators also frequently use command line programs fromwithin scripts. For example, an administrator might schedule a scriptthat automatically executes a command to distribute certain profiles totheir subscribers every night.

Client Program RequirementsSince stand-alone client programs are just regular C programs, theymust do certain things at start-up to prepare to use the TME 10 clientservices.

■ The program must initialize the TME 10 framework. Thetmf_init function initializes the ORB run-time and pre-loads anyinterfaces that your client program will use.

■ The program must register itself as a client. All clientprograms must declare themselves to the ORB. Your programmust calltmf_client_init prior to the first method invocation.

■ The program must explicitly create its own transactioncontext. If your CLI program invokes Tivoli-style methods, theymust run within the context of a transaction. Since the CLIprogram is just a client program, however, there is no implicittransaction context as there is inside a method. The CLI programmust manually start a transaction withtmf_trans_begin. Theprogram must also manually commit or abort the transactionwhen appropriate.

In the next section, we will look at how the Tivoli/Phone applicationimplements its client programs and how it satisfies the aboverequirements.

Page 239: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Tivoli/Phone CLI Commands

Application Development with TME 10 ADE 8–3

Writing C

lient Program

s

Tivoli/Phone CLI CommandsThe Tivoli/Phone application provides six command line utilities thatprovide non-graphical access to application operations. Thecommands are shown in the table below.

All the command-based utilities in the Tivoli/Phone application arelinks to a single, common executable. The program maintains a statictable of commands and their corresponding functions. When a userruns a CLI command, the program looks up the requested commandand invokes the appropriate function. Putting all the CLI commandsinto a single executable cuts down on the amount of duplicated setupcode and reduces disk space requirements. The only significantdrawback to the single-executable approach is that anytime you add anew command, you must recompile and re-link the executable.

Note: Placing all CLI commands under a single executable workswell on UNIX systems, since you can use theln command tocreate a link between each command and the central program.On other systems, such as Windows NT, this strategy may notbe possible.

The code for the Tivoli/Phone CLI program is shown below.1 #include <tivoli/tas_init.h>

2 #include <tivoli/tmfrt.h>

3 #include <tivoli/phone.h>

4

5 typedef struct {

Command Purpose

waddphn Adds an entry to a profile

wdelphn Removes an entry from a profile

weditphn Changes the attributes of an entry

wgetphn Returns an entry given a name and phone number

wphone Looks up entries that match a given name

wpopphn Populates a profile from an import file

Page 240: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Tivoli/Phone CLI Commands

8–4 Version 3.6

6 char *name;

7 void (*func)();

8 } function_table_t;

9

10 /* Define a table of commands and their functions */

11 static function_table_t cli_cmds[] = {

12 {"waddphn", waddphn},

13 {"wgetphn", wgetphn},

14 {"wphone", wphone},

15 {"wpopphn", wpopphn},

16 {"weditphn", weditphn},

17 {"wdelphn", wdelphn},

18 {NULL, NULL}

19 };

20

21 int main(int argc, char **argv)

22 {

23 type_repository *t[2];

24 int volatile status = 0;

25 function_table_t *fp;

26

27 t[0] = phone_type_repository;

28 t[1] = type_repository_null;

29

30 /* Setup the runtime environment */

31 tmf_init(t);

32 tmf_client_init();

33 tas_init();

34

35 /* Set up a top level transaction */

36 if (tmf_trans_begin(OC_REVOCABLE_T) == NULL) {

37 tmf_client_exit(2);

38 return(2);

39 }

40

41 Try {

42 fp = cli_cmds;

43

44 /*

45 * Find the requested command in the

46 * table and invoke the function.

47 */

Page 241: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Tivoli/Phone CLI Commands

Application Development with TME 10 ADE 8–5

Writing C

lient Program

s

48 while (fp->name != NULL) {

49 if (strcmp(fp->name,

50 basename(argv[0])) == 0) {

51 fp->func(argc, argv);

52 break;

53 }

54 fp++;

55 }

56

57 tmf_trans_end();

58 }

59 ...

60 Catch(Exception, ex) {

61 char *msg;

62

63 /* Bind any error message */

64 if ((msg = tmf_ex_msg_bind(ex, NULL, 0)) == NULL)

65 msg = "Could not format exception error";

66

67 fprintf(stderr, "%s\n", msg);

68 mg_free(msg);

69

70 status = 2;

71 tmf_trans_abort();

72 }

73 EndTry;

74

75 tmf_client_exit(status);

76 return(status);

77 }

The first thing the client program must do is initialize the various TME10 client services. Thetmf_init function initializes the run-time. Thetmf_client_init function registers the program as a client. Thetas_initfunction initializes the Tivoli Application Services library (libtas).

Thetmf_init function (line 31) provides a way to pre-load informationabout the interfaces that the program will use. When a client calls amethod stub, the TME 10 run-time must look up information in theTME 10 interface repository to get information about the methodparameters and data types. You can gain a small performance benefitby pre-loading repository information when your program starts. You

Page 242: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Tivoli/Phone CLI Commands

8–6 Version 3.6

can find the repository name in the public header file generated by theTIDL compiler. The Tivoli/Phone client program, for example,pre-loads information about thephone_type_respository.

type_repository *t[2];

...

t[0] = phone_type_repository;t[1] = type_repository_null;

/* Setup the runtime environment */tmf_init(t);tmf_client_init();tas_init();

After it initializes the TME 10 client services, the program callstmf_trans_begin to create a top-level transaction. The program mustcreate a transaction, since all Tivoli-style methods that the programinvokes must run in the context of a transaction.

/* Set up a top level transaction */if (tmf_trans_begin(OC_REVOCABLE_T) == NULL) { tmf_client_exit(2); return(2);}

In addition to starting the transaction, the program must also abort orcommit the transaction as necessary. For example, if one of thecommand functions throws an exception, the program usestmf_trans_abort to abort the transaction.

Catch(Exception, ex) { char *msg;

/* Bind any error message */ if ((msg = tmf_ex_msg_bind(ex, NULL, 0)) == NULL) msg = "Could not format exception error";

fprintf(stderr, "%s\n", msg);

...

/* Abort the transaction */ tmf_trans_abort();}EndTry;

Page 243: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Tivoli/Phone CLI Commands

Application Development with TME 10 ADE 8–7

Writing C

lient Program

s

Each Tivoli/Phone CLI command is a function that is called from themain function of the CLI program. The program maps the requestedcommand to the supporting function and invokes it.

Try { fp = cli_cmds;

/* * Find the requested command in the * table and invoke the function. */ while (fp->name != NULL) { if (strcmp(fp->name, basename(argv[0])) == 0) { fp->func(argc, argv); break; } fp++; }...}EndTry;

The code from thewgetphn function is shown below. The functionretrieves a given entry from aPhoneListProfile profile and prints thecontents of the entry to standard output.1 void wgetphn(int argc, char **argv)

2 {

3 TMF_Types_StringList classes;

4 char *name, *phone, *profile_name;

5 char *key;

6 Object profile;

7 TPL_PhoneEntryInfo entry;

8 ml_t *mh = ml_create();

9 Environment ev = {0};

10

11 /* Count the number of arguments */

12 if (argc != 4) {

13 ExPhoneError *ex = ExPhoneErrorNew(

14 phone_cli_msg,

15 wgetphn_usage);

16 Throw(ex->type_name, ex);

17 }

18

19 seq_init((sequence_t *)&classes);

20 memset(&entry, 0, sizeof(TPL_PhoneEntryInfo));

Page 244: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Tivoli/Phone CLI Commands

8–8 Version 3.6

21

22 profile_name = argv[1];

23 name = argv[2];

24 phone = argv[3];

25

26 /* Convert the object label into an objref */

27 profile = cli_lookup_object(&classes,

28 profile_name);

29 ml_attach_Object_reference(mh, profile);

30

31 /* Build the record key from the arguments */

32 entry.name = name;

33 entry.phone = phone;

34 key = make_record_key(&entry);

35

36 /* Get the specified entry */

37 t_TPL_PhoneListProfile_get_phone_entry(profile,

38 &ev,

39 Trans_sub,

40 key,

41 &entry);

42

43 /* Print the entry’s information */

44 dump_entry(&entry);

45

46 ml_destroy(mh);

47 }

Page 245: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Development with TME 10 ADE A–1

Reference

ATivoli/Phone Build Environment

The heterogenous nature of TME 10 requires that an application beable to run on a diverse set of platforms. Creating a cross-platformbuild environment can be one of the trickiest tasks of applicationdevelopment. You must account for variations in tool location,required compiler flags, library formats, and so on. For example,consider the task of building an archive library. The location of thearcommand varies across platforms. Some platforms also require you torun ranlib on the library while others do not have this command. Yourbuild environment must be able to do the correct thing for eachplatform.

This appendix examines how the build environment of theTivoli/Phone application is constructed. The first two sections shouldhelp you become familiar with the structure of the Tivoli/Phone sourcetree and to build the application. Later sections show how to constructa build environment to isolate and minimize platform-specificrequirements.

The Tivoli/Phone build environment uses GNUmake and the GNU Ccompiler for UNIX platforms and Visual C++ for NT. If you do nothave these tools, you can get them from the Tivoli ProductivityPackage.

A

Page 246: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The Tivoli/Phone Source Tree

A–2 Version 3.6

The Tivoli/Phone Source TreeThe diagram below shows the structure of the Tivoli/Phone sourcecode directory.

■ Endpoint—Contains files unique to the endpoint side. Buildsendpoint method binaries.

■ Common—Contains files common to both endpoint andplatform. Note that no builds take place in this directory; thereare no makefiles. The common files are referenced by relativepath from the endpoint and platform directories.

• plbo—IDL files for thePhoneEndpoint class; methodimplementations for theupdate_phone anddiscover_phonelistoperations.

• ppo—IDL files for thePhoneListProfile class; variousfunctions used by the class.

sample_app

endpoint platformcommon

src src

build.mk

cli ppoplbo

Bitmaps Dialogs

plbo ppocross

plbo ppo inc plbo ppo

install

config build.mk

Page 247: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The Tivoli/Phone Source Tree

Application Development with TME 10 ADE A–3

Reference

■ Platform—Contains files unique to the platform side. Buildsserver-side binaries and methods. Contains:

• cli—Source code for the application CLI commands.

• ppo—Methods to implement thePhoneEndpoint class.

• plbo—Methods for thePhoneListProfile class.

■ Install—Contains files to build an installable image for thesample application.

Thebuild.mk file, located at the top level, defines variables used bythe application make files. Thebuild.mk file is well-commented andcontains instructions about setting these variables.

If necessary, set SRC_DIR to the path where the sample applicationsare installed. It should point to the top-level directory wherebuild.mkand theconfig directory are found (for example,/usr/local/Tivoli/src).

If you are cross-compiling (that is, compiling for a platform other thanthe one you are running on), you must set theINTERP variable to theplatform you want to compile for.

When you source thesetup_env script that ships with TME 10, it setsBINDIR . Thesetup_env script is found in/etc/Tivoli on UNIX and%SystemRoot%\system32\drivers\etc\Tivoli on NT. You do notneed to set this variable manually.

TIVOLI_DIR is used to locate the ADE includes, libraries, andcommands. Assuming you have installed ADE in the same directory

Cross-compilingCross-compiling consists of building on a tier 1 platform to generatecode for another platform. You must cross-compile when you arebuilding for a platform that does not support ADE but that does have acompiler. ADE is not supported on platforms such as NetWare, OS/2,and Windows95.

For example, to build the sample application to run on Windows95, youcan compile on NT using the Visual C++ compiler. See the table in“Platform-specific Definitions” on page A-7 for a list of platforms forwhich you must cross-compile.

Page 248: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Building Tivoli/Phone

A–4 Version 3.6

where the TME 10 binaries are located, this path can be set to thetop-level installation directory (for example,/usr/local/Tivoli onUNIX and c:/Tivoli on NT).

In addition, for NT platforms only, you must be sure two additionalpaths are set for your environment. You must set the path to yourMicrosoft Visual C++ 4.x directory (for example,c:/msdev) and thepath to your Tivoli NT tools directory.

By default, these are environment variables. For Visual C++, theenvironment variable isMSDevDir, which is set when you installVisual C++. The path to your Tivoli NT tools directory is normally$BINDIR/tools and is set during the TME 10 ADE installation.

Building Tivoli/PhoneTo build the Tivoli/Phone application, change directories to the toplevel of the build tree and typemake everything. This builds theTivoli/Phone and copies all deliverables to the export directory.

1. If necessary, set theSRC_DIR andTIVOLI_DIR variables inbuild.mk .

2. Source the filesetup_env. This is found in/etc/Tivoli on UNIXand%SystemRoot%\system32\drivers\etc\Tivolion NT.

3. If you are cross-compiling, setINTERP (in build.mk ) to be theplatform you are compiling for. If you are not cross-compiling,you do not need to set this;INTERP will be the value set bysetup_env.

4. In the build tree, change directory tosrc.

5. At the command line, enter:

make everything

The Export DirectoryWhen you runmake everything in the Tivoli/Phone build tree, itcopies all targets from the build tree to the export directory. Thelocation of the export directory is defined by theEXPORT_DIRvariable inbuild.mk .

Page 249: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

The Export Directory

Application Development with TME 10 ADE A–5

Reference

The figure below shows the structure of the Tivoli/Phone exportdirectory.

■ Thebin directory contains the application binaries. The methodbinaries go in theTME/PHONE subdirectory; the CLIcommand binaries go in thebin subdirectory.

■ The include directory contains the application’s public headerfiles.

■ Thecfg directory contains the scripts and configuration filesnecessary to install the application’s classes.

■ Underbin, thelcf-bundle directory contains the LCF endpointcode. It is a mirror ofbin and repeats the same hierarchy of files.

export_dir

bin includecfg

TME bin

interp interp interp

tivoli

TME

PHONE

PHONE

tivoliLCF

test

lcf_bundle

interp

bin

test

TME

PHONE

Page 250: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Creating a Multi-platform Environment

A–6 Version 3.6

Creating a Multi-platform EnvironmentThe make files in the Tivoli/Phone environment share many commonvariables, macros, and rules. These are stored in theconfig directory.There are four types of build information stored in theconfig directory.

■ General defaults—Basic variables and macros that are commonto all components.

■ Platform-specific definitions—Platform-specific informationsuch as compiler flags, libraries, and command paths.

■ Implicit build rules—Definitions for implicit rules, such asinstall. Tivoli/Phone also defines several pattern rules to simplifythe dependencies for IDL and DSL targets.

■ Endpoint-specific build rules and macros—Endpoint-specificinformation such as compiler flags, libraries, and commandpaths.

General DefaultsAll basic variable definitions and macros required by the buildenvironment are defined in these main files:

■ top.mk—In src/config. Specifies TOP and SUBDIRS.

■ global.mk—In src/config. Includes environment variables suchas the location of the export directory, system commands, Tivolibuild utilities, and macros related to various tools.

Page 251: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Creating a Multi-platform Environment

Application Development with TME 10 ADE A–7

Reference

Platform-specific DefinitionsEach supported platform has a rule file in theconfig directory thatcontains platform-specific bindings for make variables, such ascommand paths and compiler flags. The name of each file isinterp.mk,whereinterp is the TME 10 interpreter type. The table below showssome common interpreter types.

Interpreter Type PlatformNeed to

Cross-compile?

aix3-r2 AIX 3.0 No

aix4-r1 AIX 4.1 No

hpux9 HP-UX 9.0 No

hpux10 HP-UX 10 No

nw3 NetWare 3 Yes, using Watcomon NT

nw4 NetWare 4 Yes, using Watcomon NT

os2 OS/2 Yes, using Watcomon NT

solaris2 Solaris 2 No

sunos4 SunOS 4 No

w32-ix86 NT No

win3x Windows 3.x Yes, using VisualC++

win95 Windows 95 Yes, using VisualC++

Page 252: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Creating a Multi-platform Environment

A–8 Version 3.6

The contents of thesolaris2.mk file is shown below. This file containsthe platform-specific definitions for the Solaris2 platform. The filedefines the locations of the basic tools, defines the flags that are passedto the C and C++ compilers, and specifies extensions for shared andother libraries.

1 #

2 # Compiler

3 #

4 CC = gcc

5

6 #

7 # Debug and non-debug flags, in turn.

8 #

9 ifeq ($(strip $(PROD_BUILD)),)

10 CFLAGS = -Wall -g

11 else

12 CFLAGS = -Wall -O2

13 endif

14

15 # <a name=pic></a>

16 # How to generate position-independent code for shared libraries

17 #

18 c-pic-flag = -fpic

19

20 #

21 # Flags to pass to cpp. INCDIRS is defined in global.mk.

22 #

23 ifneq ($(strip $(ENDPOINT_BUILD)),) # ENDPOINT_BUILD

24 CPPFLAGS = -DSOLARIS -DSOLARIS2 -DSVR4 -DNO_STRINGS_H

25 else # ENDPOINT_BUILD

26 CPPFLAGS = -DTLI -DSOLARIS -DSOLARIS2 -DSVR4 \

27 -DHAVE_BOOL_T -DHAVE_LIMITS_H=1 -DHAVE_STDDEF_H=1\

28 -DHAVE_SYS_FCNTL_H=1 -DHAVE_SYS_FILIO_H=1-DTIMESPEC_IN_SYS_TIME=1\

29 -DHAVE_SETSID=1 -U__STRICT_ANSI__ -D__STDC__=0-DUSE_POSIX_SIGNALS

30 endif # ENDPOINT_BUILD

31

32 CPPFLAGS += $(INCDIRS)

33

34 ##########################################################

Page 253: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Creating a Multi-platform Environment

Application Development with TME 10 ADE A–9

Reference

35 # C++ Compilation Macros

36 ##########################################################

37

38 #

39 # Compiler

40 #

41 CXX = g++

42

43 #

44 # Debug and non-debug flags, in turn.

45 #

46 ifeq ($(strip $(PROD_BUILD)),)

47 CXXFLAGS = -Wall -g -O

48 else

49 CXXFLAGS = -Wall -O2

50 endif

51

52 #

53 # C++ CPPFLAGS (added to CPPFLAGS)

54 #

55 CXX_CPPFLAGS =

56

57 #

58 # How to generate position-independent code for shared libraries

59 #

60 cxx-pic-flag = -fpic

61

62 ##########################################################

63 # Link Macros

64 ##########################################################

65

66 #

67 # What to link libraries with. (We link executables with CC and CXX.)

68 #

69 LD = ld

70

71 #

72 # Debug and non-debug link flags. Note that LDFLAGS is passed to the

73 # compiler to link executables, whereas LD_SO_SWITCH is passed to LD

74 # to build shared libraries.

75 #

76 ifeq ($(strip $(PROD_BUILD)),)

Page 254: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Creating a Multi-platform Environment

A–10 Version 3.6

77 LDFLAGS =

78 LD_SO_SWITCH = -G

79 else

80 LDFLAGS = -s

81 LD_SO_SWITCH = -G

82 endif

83

84 #

85 # Extension to use for shared libraries

86 #

87 SO = so

88

89 #

90 # Standard C++ libraries

91 #

92 #

93 LIBCXX = -lg++ -lm

94

95 #

96 # Communication and networking libraries

97 #

98 LIBCOMM = -lsocket -lnsl

99 LIBNET =

Implicit Build RulesTherules.mk file defines implicit build rules that all make files in theenvironment use. For example,rules.mk contains definitions for theall andinstall rules. Placing these rules in therules.mk file ensuresthat all make files in the build environment support the same minimumset of rules.

The rules.mk also defines several pattern rules. Pattern rules useregular expressions to create implicit target/dependency relationships.Consider dialog descriptor files for example. By convention, compileddialogs have file names that end in the extension.d. The source for acompiled dialog has the same root file name, but ends in the extension.dsl. So,phone_props.dsl produces thephone_props.d dialogdescriptor.

Page 255: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Creating a Multi-platform Environment

Application Development with TME 10 ADE A–11

Reference

The rules.mk file defines a pattern rule that creates atarget/dependency relationship between.d and.dsl files.

%.d : %.dsl$(compile-dsl)

The above rule matches files that have a.d extension and searches fora .dsl file with the same root name. Ifmake finds a match, it performsdependency checking and builds the target if necessary.

The make file from theppo/Dialogs directory illustrates the implicitbuild rule in action.1 ...

2 HERE = ppo/Dialogs

3 TOP = ../../..

4 include $(TOP)/configure.mk

5

6 DSL-SRCS = \

7 phone_icon.dsl \

8 add_dialog.dsl \

9 edit_dialog.dsl \

10 phone_props.dsl

11

12 INCDIRS += -I..

13

14 DSL-OBJS = $(DSL-SRCS:%.dsl=%.d)

15

16 stubs-targets = $(DSL-OBJS)

17

18 cfg-dir = $(EXPORT_DIR)/cfg/$(INTERP)/TME/PHONE

19 all-targets = $(addprefix $(cfg-dir)/, $(DSL-OBJS))

20

21 clean-targets = $(DSL-OBJS)

22 depends-targets =

23

24 include $(SRC_DIR)/config/rules.mk

The make file defines a list of DSL source files and their descriptorcounterparts. The file does not explicitly define the relationshipbetween the two lists, since the pattern rule inrules.mk takes care ofit.

Page 256: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Creating a Multi-platform Environment

A–12 Version 3.6

Endpoint-specific Rules and MacrosThis section discusses build rules and macros specific to endpoints thatspecify where to export files and what targets to build. Thesepre-defined path names are used to build path names to include in thetarget variables.

You must set the following variables to specify the location of exportfiles:

■ cfg-dir—Specifies the directory to which configuration scriptsare exported

■ meth-dir—Specifies the directory to which method binaries areexported

■ bin-dir —Specifies the directory to which method binaries areexported

■ lib-dir —Specifies the directory to which public libraries areexported

■ inc-dir —Specifies the location to which header files and IDLsource files are exported

You must also set the following four targets:

■ depends-targets

■ includes-targets

■ stubs-targets

■ all-targets

In adddition,SUBDIRS specifies what subdirectories to visit to buildtargets, andPRE-SUBDIRS defines special rules, with dependenciesoff, to generate files needed beforemake-depends can run.

Page 257: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Development with TME 10 ADE Index–1

Index

Symbols_get_validation_enabled operation 4-11

Aabstract classes 2-13access control lists 1-14, 2-28add_record operation 3-6, 3-17add_records operation 5-5ANSI C 2-17any data type 2-5, 3-22application design

data flow diagrams 1-5exceptions 1-17extensibility 1-20identifying classes 1-8identifying operations 1-6internationalization 1-21scalability 1-18security considerations 1-14using transactions 1-14

application development cycle 1-3application scalability 5-1authentication 5-2authorization roles 1-14

Bbase Tivoli exception 2-4build rules

general defaults A-6implicit A-10pattern A-10

platform-specific A-7build.mk file A-3

Ccallbacks

explained 7-11gadget library 7-11, 7-14, 7-14–

7-18IDL-style 7-11

Catch statement 2-5ccms_init_callbacks function 7-43ccms_read_pushed_records function 6-17ccms_read_update_parameters function

6-17ccms_register_table function 7-43cell text function 7-38changing a record key 3-31changing validation status 4-9class declarations 2-12class inheritance 2-15class install scripts 2-41classes

identifying 1-8supported interfaces 1-8

CLI commands 8-1, 8-3client programs

explained 8-1client stubs 1-19, 2-2, 2-39command methods 2-19compiler output 2-39compiling an IDL description 2-39config directory A-6ContextThrow statement 3-4, 3-21controls 7-7copy_records operation 4-21CORBA specification 1-3CORBA templates 2-41create_db operation 3-2

Page 258: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Index–2 Version 3.6

create_entries operation 5-4create_phone_entries operation 3-17,

4-22create_phone_entry operation 3-17creating a notice group 2-33creating profile records 3-16custom roles 2-28

Ddaemon servers 2-22, 2-25, 5-15, 7-20data abstraction 3-13data flow diagrams 1-5, 1-9Database interface

add_record 3-6, 3-17add_records 5-5delete_record 3-28dump_some_db 5-22get_default_policies 3-6get_record 3-22, 3-32, 4-3, 4-12get_validation_policies 3-6set_record_flags 4-10set_values 3-33, 4-6

db_name attribute 3-8, 3-9deep copies 4-4default_push_params attribute 3-8, 3-10defining method roles 2-29delete_phone_entries operation 3-27delete_phone_entry operation 3-27delete_record operation 3-28deleting profile records 3-27desktop services 7-1destroy_iterator operation 2-25, 5-17dialogs 7-7

controls 7-7descriptors 7-8launching 7-18states 7-8

disable_validation operation 4-9

discover_phonelist operation 2-27, 4-17,6-4

display flag 3-7dont_care flag 3-11DSL 7-8dump_some_db operation 5-22

Eenable_validation operation 4-9endpoint class 1-12endpoint method 3-10, 6-14endpoints 1-7, 6-1exceptions

catching any type 2-5defining in IDL 2-4design considerations 1-17families of 2-5inheritance 2-4

execution privileges 2-28ExException exception 2-4, 2-5, 3-21ExExists exception 3-4, 3-21ExFileWDenied exception 3-4ExInvalid exception 2-7ExPhone exception 1-18ExPhoneError exception 2-4expose mechanism 7-38

Ffind_by_name operation 2-25, 5-16fixed records 3-24, 3-31, 3-33force levels 3-10, 6-18friendly class name 2-18

Page 259: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Development with TME 10 ADE Index–3

Ggadget library

hierarchy 7-13operations 7-12

get_all_entries operation 2-25, 5-16,7-29

get_cell_data function 7-39get_default_policies operation 3-6, 4-3get_phone_entries operation 3-22, 4-22get_phone_entry operation 3-22get_record operation 3-22, 3-32, 4-3,

4-12get_validation_policies operation 3-6, 4-5glDialog object 7-14glDialog_present operation 7-24glDialog_run operation 7-24glyphs 7-32GNU C compiler A-1GNU make A-1graphical interface

callbacks 7-11components 7-6dialogs 7-7icons 7-6presentation object 7-9

Iicon states 7-10icons 7-6identifying classes 1-8IDL

compiling 2-39components 2-1header files 2-40installation specification 2-28introduction 1-3program specifiction 2-18Tivoli extended IDL 2-1

IDL compiler 2-1IDL data types 2-2implementation models 2-19implementation specification

contents 2-1defined 2-12inheritance 2-13method overides 4-14Tivoli/Phone 2-14

implicit build rules A-6import file 6-5importing profile records 6-4initializ operation 3-2initializing client services 8-5initpres command 7-10, 7-45installation specification

contents 2-1defined 2-28

install-time commands 2-32instantiable classes 2-13interface definition

attributes 2-7contents 2-1data types 2-2exception declarations 2-4operation signatures 2-6specifying interfaces 2-6

Interface Definition Languagesee IDL

interface repository 8-5interfaces 1-8

defined 1-2inheritance 1-8

internationalization 1-21inter-object message service 1-19intrinsic methods 2-20IOM channel

diagram 5-3IOM service 1-19, 2-22, 5-2iteration 1-19, 5-2, 5-13

Page 260: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Index–4 Version 3.6

iterator implementation 5-20iterator server 5-14, 5-18iterator-based operations 2-25

Llanguage bindings 2-17, 2-41launching a dialog 7-18libccms_gui library 7-45, 7-46libtable library 7-25local memory handles 3-23locales 1-21lock promotion 6-22logging a notice 3-21, 3-29, 4-16

Mmake_record_key function 7-41ManagedNode class 6-2managing tabular data 7-24MDist service 6-17memory management

and exceptions 3-23message catalogs 1-22metaclasses 2-13method binaries 2-28method execution styles 2-20method templates 2-41METHODPATH variable 2-33ml_destroy function 3-23modality 7-24modify_phone_entry operation 3-31, 7-41modifying profile records 3-30move_records operation 4-21

Nnext_entries operation 2-25, 5-17nmval data type 3-11nmval_list data type 3-19, 4-4nobody account 1-17notices 3-21

Oobject oriented analysis 1-5OBJECT_NIL 3-19, 5-14ObjectLabel data type 3-18operation bindings 2-17operation privileges 1-16operation signatures 2-6ORB

see TME ORBoveriding implementations 2-15overriding method implementations 4-14

Pparallel daemons 2-22parent stubs 4-14partition attribute 3-8, 3-9pattern rules A-10pe_classname field 3-7per-method servers 2-21, 2-27persistent state data 5-18phone list import file 6-5phone.init script 2-32phone_core method binary 2-31Phone_prog1 server program 2-25Phone_prog2 server program 2-26phone_query method binary 2-31phone_ui method binary 2-31Phone_ui_prog1 server program 2-27

Page 261: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Development with TME 10 ADE Index–5

PhoneEndpoint classimplementation specification 2-17installation specification 2-34program specification 2-27

PhoneEntryGUI interfaceinheritance 2-8ui_phone_props 1-12, 2-27

PhoneEntryInfo data type 3-13, 3-16,3-17, 3-25, 3-33, 6-5, 6-18,7-26, 7-39

PhoneEntryInfo type 2-2, 2-3PhoneEntryInfoList data type 7-31PhoneListGUI interface

ui_phone_props 7-19PhoneListIterator interface

defined 2-8destroy_iterator 2-25, 5-17next_entries 2-25, 5-17

PhoneListProfilefind_by_name 2-25get_all_entries 5-16, 7-29modify_phone_entry 7-41PhoneEntryInfo data type 7-26, 7-39ui_phone_props 7-43

PhoneListProfile classdesign 1-8implementation specification 2-14installation specification 2-28method binaries 2-31program specification 2-24

PhoneListProfile interfaceauthorization map 1-16characteristics 1-8create_phone_entries 3-17, 4-22create_phone_entry 3-17delete_phone_entries 3-27delete_phone_entry 3-27exceptions 1-18find_by_name 5-16get_all_entries 2-25get_phone_entries 3-22, 4-22

get_phone_entry 3-22inheritance 1-12, 2-8modify_phone_entry 3-31PhoneEntryInfo data type 2-2, 2-3,

3-25, 3-33, 6-5, 6-18PhoneEntryInfoList 7-31supported operations 1-10

platform-specific build rules A-7plbo interface

characteristics 1-13definition 2-11discover_phonelist 2-27, 4-17, 6-4implementation of 2-17, 6-2inheritance 2-11update_phone 2-27, 6-15

plbo_prog1 server program 2-27pm_classname field 3-7policy

fetching policy records 4-3initial profile policy 3-10policy records 3-4script-valued policy 3-12setting 4-6

policy records 3-4, 3-10, 4-3policy validation 4-12PolicyDrivenBase interface 2-11polymorphism 2-12populate operation 3-17, 4-16, 6-4post-distribution processing 6-14Presentation interface 7-9presentation objects 7-9privileges 1-16profile endpoints 1-7, 6-1Profile interface

_get_validation_enabled 4-11attributes 2-7copy_records 4-21db_name attribute 3-8, 3-9default_push_params 3-10default_push_params attribute 3-8disable_validation 4-9

Page 262: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Index–6 Version 3.6

enable_validation 4-9get_default_policies 4-3get_validation_policies 4-5move_records 4-21partition attribute 3-8, 3-9populate 3-17, 4-16, 6-4profile_organizer attribute 3-9record_key attribute 3-8remove 4-14set_default_policies 4-6set_validation_policies 4-6standard implementations 4-1the_context attribute 3-8, 3-9validate operation 4-12

Profile interface profile_organizer attribute3-8

profile records 3-13profile_organizer attribute 3-8, 3-9ProfileEndpoint class 1-12ProfileOrganizer interface

create_db 3-2validate 4-13

profilesdesign criteria 1-7

program methods 2-19program specification 2-18

contents 2-1push_params data type 3-10

Rr_fixed flag 3-33r_readonly flag 3-32read-only records 3-24record_key attribute 3-7, 3-8registering as a client 8-2related methods 4-2remove operation 4-14removing a profile 4-14

repository name 8-6retrieving records 3-22roles 1-14rules.mk file A-10

Sscalability 5-1scalable input 5-2, 6-17security

authorization 1-14privileges 1-16

sequences 2-3server programs 2-20server skeletons 1-19, 2-2, 2-40set_default_policies operation 4-6set_record_flags operation 4-10set_sensitive operation 7-12set_validation_policies operation 4-6set_values operation 3-33, 4-6setting policy records 4-6shared daemons 2-23spawning a thread 5-11starting a transaction 8-2stub names 2-39

Tt_TypeCode_decode function 5-8Table controls 7-24table manager library

cell text function 7-38defined 7-25defining columns 7-34display cache 7-26expose mechanism 7-38manipulating rows 7-40registering with 7-32

Page 263: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Application Development with TME 10 ADE Index–7

requirements 7-25sorting records 7-37TME support dialogs 7-43

TableMgrGuiDlgs presentation object7-11, 7-45

tds_table_add_column function 7-34,7-35

tds_table_add_row function 7-40tds_table_change_row function 7-40tds_table_change_row_by_key function

7-40tds_table_expose_cb callback 7-38tds_table_load_cache function 7-27tds_table_register_table function 7-32tds_table_set_sort_column function 7-37the_context attribute 3-8, 3-9threads

spawning 5-11use with IOM 5-3

TIDL compiler 2-33, 2-39tidlc command 2-39Tivoli Name Registry 2-33Tivoli Productivity Package A-1Tivoli/AEF 1-20Tivoli/Phone

authorization map 1-15classes 1-8database design 1-5get_cell_data function 7-39introduction 1-4make_record_key 7-41PhoneListProfile class behavior 1-8source code A-1

Tivoli/Visual DSL 7-8TME 10 ORB 5-1TME desktop 7-1TME ORB 2-2, 2-20, 2-22, 7-31TME support dialogs 7-11, 7-43, 7-45TMF_CCMS module

Database interface 3-17, 3-22,

3-28, 3-32Profile interface 1-9, 2-7, 2-14,

2-24, 3-2, 4-1ProfileOrganizer interface 3-2

tmf_client_init function 8-2tmf_free_generic function 7-31tmf_init function 8-2tmf_trans_begin function 8-2TMF_UI module

Presentation interface 7-9UserInterfaceBase interface 2-8, 2-14

tmfMsgAdd macro 3-30TPL_PhoneListProfile_CO variable 2-33transaction locks 6-22transactions 1-14

Uui_phone_props operation 1-12, 2-27,

7-19, 7-43update_phone operation 2-27, 6-15user interface

daemon server 2-26UserInterfaceBase interface 2-8, 2-14

Vval_disabled flag 4-9, 4-10, 4-11validate operation 4-12validating a profile 4-12validation 4-9

Wwaddphn command 8-3WD_DESKTOP_OID variable 7-20WD_DESKTOP_PID variable 7-20

Page 264: Application Development with TME 10 ADE - IBMpublib.boulder.ibm.com › tividd › td › ADE › WorkBk › en_US › ... · Application Development with TME 10 ADE v Preface TME

Index–8 Version 3.6

WD_OCO_OID variable 7-20wdelphn command 8-3weditphn command 8-3wgetphn command 8-3winstendpt command 6-3wphone command 8-3wpopphn command 8-3

XX/Open message catalogs 1-22