<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en-us" xml:lang="en-us">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="security" content="public" />
<meta name="Robots" content="index,follow" />
<meta http-equiv="PICS-Label" content='(PICS-1.1 "http://www.icra.org/ratingsv02.html" l gen true r (cz 1 lz 1 nz 1 oz 1 vz 1) "http://www.rsac.org/ratingsv01.html" l gen true r (n 0 s 0 v 0 l 0) "http://www.classify.org/safesurf/" l gen true r (SS~~000 1))' />
<meta name="DC.Type" content="reference" />
<meta name="DC.Title" content="C++ example: Integrating user-defined transactions into Collection Services" />
<meta name="abstract" content="This C++ example program shows how to use the Start transaction and End transaction APIs to integrate user-defined transaction performance data into Collection Services." />
<meta name="description" content="This C++ example program shows how to use the Start transaction and End transaction APIs to integrate user-defined transaction performance data into Collection Services." />
<meta name="DC.Relation" scheme="URI" content="rzahxcollservusertran.htm" />
<meta name="copyright" content="(C) Copyright IBM Corporation 1998, 2006" />
<meta name="DC.Rights.Owner" content="(C) Copyright IBM Corporation 1998, 2006" />
<meta name="DC.Format" content="XHTML" />
<meta name="DC.Identifier" content="rzahxcollservusertranexcplus" />
<meta name="DC.Language" content="en-us" />
<!-- All rights reserved. Licensed Materials Property of IBM -->
<!-- US Government Users Restricted Rights -->
<!-- Use, duplication or disclosure restricted by -->
<!-- GSA ADP Schedule Contract with IBM Corp. -->
<link rel="stylesheet" type="text/css" href="./ibmdita.css" />
<link rel="stylesheet" type="text/css" href="./ic.css" />
<title>C++ example: Integrating user-defined transactions into Collection
Services</title>
</head>
<body id="rzahxcollservusertranexcplus"><a name="rzahxcollservusertranexcplus"><!-- --></a>
<!-- Java sync-link --><script language="Javascript" src="../rzahg/synch.js" type="text/javascript"></script>
<h1 class="topictitle1">C++ example: Integrating user-defined transactions into Collection
Services</h1>
<div><p>This C++ example program shows how to use the Start transaction
and End transaction APIs to integrate user-defined transaction performance
data into Collection Services.</p>
<div class="section"><div class="note"><span class="notetitle">Note:</span> By using the code examples, you agree to the terms of the <a href="codedisclaimer.htm">Code license and disclaimer information</a>.</div>
<pre>//**********************************************************************
// tnstst.C
//
// This example program illustrates the use 
// of the Start/End Transaction APIs (qypeStartTransaction,
// qypeEndTransaction). 
// 
//
// This program can be invoked as follows:
//   CALL lib/TNSTST PARM('threads' 'types' 'transactions' 'delay')
//     where
//       threads      = number of threads to create (10000 max)
//       types        = number of transaction types for each thread
//       transactions = number of transactions for each transaction
//                      type
//       delay        = delay time (millisecs) between starting and
//                      ending the transaction
//
// This program will create "threads" number of threads. Each thread
// will generate transactions in the same way. A thread will do
// "transactions" number of transactions for each transaction type,
// where a transaction is defined as a call to Start Transaction API,
// then a delay of  "delay" millisecs, then a call to End Transaction
// API. Thus, each thread will do a total of "transactions" * "types"
// number of transactions. Each transaction type will be named
// "TRANSACTION_TYPE_nnn" where nnn ranges from 001 to "types". For
// transaction type n, there will be  n-1 (16 max) user-provided
// counters reported, with counter m reporting m counts for each
// transaction.
//
// This program must be run in a job that allows multiple threads
// (interactive jobs typically do not allow multiple threads). One
// way to do this is to invoke the program using the SBMJOB command
// specifying ALWMLTTHD(*YES). 
//
//**********************************************************************

#define _MULTI_THREADED

// Includes
#include "pthread.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "qusec.h"
#include "lbcpynv.h"
#include "qypesvpg.h"

// Constants
#define maxThreads 10000

// Transaction pgm parm structure
typedef struct 
{
  int types;   
  int trans;
  int delay;
} tnsPgmParm_t;

// Error code structure
typedef struct
{
  Qus_EC_t error;
  char     Exception_Data[100];
} error_code_t;


//**********************************************************************
//
// Transaction program to run in each secondary thread
// 
//**********************************************************************

void *tnsPgm(void *parm)
{ 
  tnsPgmParm_t *p = (tnsPgmParm_t *)parm;

  char tnsTyp[] = "TRANSACTION_TYPE_XXX";
  char pexData[] = "PEX";
  unsigned int pexDataL = sizeof(pexData) - 1;
  unsigned long long colSrvData[16] = {1,2,3,4,5,6,7,8,
                                       9,10,11,12,13,14,15,16};
  unsigned int colSrvDataL;
  char tnsStrTim[8];

  struct timespec ts = {0, 0};
  
  error_code_t errCode;

  _DPA_Template_T target, source; // Used for LBCPYNV MI instr

  unsigned int typCnt;
  unsigned int tnsCnt;
  int rc;


  // Initialize error code
  memset(&amp;errCode, 0, sizeof(errCode));
  errCode.error.Bytes_Provided = sizeof(errCode);

  // Initialize delay time
  ts.tv_sec  = p-&gt;delay / 1000;
  ts.tv_nsec = (p-&gt;delay % 1000) * 1000000;

  // Loop doing transactions   
  for (tnsCnt = 1; tnsCnt &lt;= p-&gt;trans; tnsCnt++)
  {
    for (typCnt = 1; typCnt &lt;= p-&gt;types; typCnt++)
    {
      // Set number field in transaction type 
      source.Type = _T_UNSIGNED;
      source.Length = 4;
      source.reserved = 0;
      target.Type = _T_ZONED;
      target.Length = 3;
      target.reserved = 0;
      _LBCPYNV(tnsTyp + 17, &amp;target, &amp;typCnt, &amp;source);

      // Set Coll Svcs data length in bytes
      colSrvDataL = (typCnt &lt;= 16) ? (typCnt - 1) : 16;
      colSrvDataL = colSrvDataL * 8;

      // Call Start Transaction API
      qypeStartTransaction(tnsTyp,
                           (unsigned int *)&amp;tnsCnt,
                           pexData,
                           (unsigned int *)&amp;pexDataL,
                           tnsStrTim,
                           &amp;errCode);

      // Delay specified amount
      rc = pthread_delay_np(&amp;ts);
            
      // Call End Transaction API
      qypeEndTransaction(tnsTyp,
                         (unsigned int *)&amp;tnsCnt,
                         pexData,
                         (unsigned int *)&amp;pexDataL,
                         tnsStrTim,
                         (unsigned long long *)&amp;colSrvData[0],
                         (unsigned int *)&amp;colSrvDataL,
                         &amp;errCode);
    }
  }

  return NULL;
}


//**********************************************************************
//
// Main program to run in primary thread
// 
//**********************************************************************

void main(int argc, char *argv[])
{
  // Integer version of parms
  int threads;  // # of threads
  int types;    // # of types
  int trans;    // # of transactions
  int delay;    // Delay in millisecs

  pthread_t threadHandle[maxThreads];
  tnsPgmParm_t tnsPgmParm;
  int rc; 
  int i;


  // Verify 4 parms passed  
  if (argc != 5)
  {
    printf("Did not pass 4 parms\n");
    return;
  }

  // Copy parms into integer variables 
  threads = atoi(argv[1]);
  types   = atoi(argv[2]);
  trans   = atoi(argv[3]);
  delay   = atoi(argv[4]);

  // Verify parms
  if (threads &gt; maxThreads)
  {
    printf("Too many threads requested\n");
    return;
  }

  // Initialize transaction pgm parms (do not modify
  // these while threads are running)  
  tnsPgmParm.types = types;
  tnsPgmParm.trans = trans;
  tnsPgmParm.delay = delay;

  // Create threads that will run transaction pgm
  for (i=0; i &lt; threads; i++)
  {
    // Clear thread handle
    memset(&amp;threadHandle[i], 0, sizeof(pthread_t));
    // Create thread 
    rc = pthread_create(&amp;threadHandle[i],      // Thread handle
                        NULL,                  // Default attributes
                        tnsPgm,                // Start routine
                        (void *)&amp;tnsPgmParm);  // Start routine parms
    if (rc != 0)
      printf("pthread_create() failed, rc = %d\n", rc);
  }

  // Wait for each thread to terminate
  for (i=0; i &lt; threads; i++)
  {
    rc=pthread_join(threadHandle[i],  // Thread handle
                    NULL);            // No exit status
  }

}  /* end of Main */</pre>
</div>
</div>
<div>
<div class="familylinks">
<div class="parentlink"><strong>Parent topic:</strong> <a href="rzahxcollservusertran.htm" title="Collection Services and performance explorer collect performance data that you define in your applications.">User-defined transactions</a></div>
</div>
</div>
</body>
</html>