amsample.c
/****************************************************************************/
/* */
/* Copyright 1997-2017 Teradata Corporation. */
/* ALL RIGHTS RESERVED. */
/* Teradata Corporation CONFIDENTIAL AND TRADE SECRET */
/* */
/* This copyrighted material is the Confidential, Unpublished */
/* Property of the Teradata Corporation. This copyright notice */
/* and any other copyright notices included in machine readable */
/* copies must be reproduced on all authorized copies. */
/* */
/* Purpose: Present a sample Access Module that */
/* generates arbitrary data blocks without I/O */
/* */
/* Max reads accepted is 100000000 */
/* Max logical records per block is 100000 */
/* */
/* */
/* Data returned conforms to the following TeraBuilder schema: */
/* DEFINE SCHEMA PRODUCT_SOURCE_SCHEMA */
/* DESCRIPTION 'PRODUCT INFORMATION SCHEMA' */
/* ( */
/* COL1 INTEGER, */
/* COL2 INTEGER, */
/* COL3 INTEGER, */
/* COL4 VARCHAR(7) */
/* ); */
/* */
/* Initialization string: */
/* "BLOCKCOUNT=<i>,RECORDCOUNT=<j>,TRACE <filename> <tracelevel>" */
/* */
/* Contents: */
/* PIDMMain - receives all Access Module calls from the */
/* Teradata Client Utility via the Data Connector. */
/* */
/****************************************************************************/
#include <stdio.h>
#include <string.h>
#include "pmdcomt.h"
#include "pmddamt.h"
/*#define TPT_VERSION 1 */
#ifdef TPT_VERSION
#define MODULE_NAME "amsample_TPT"
#define ENVIRONMENT "Teradata Parallel Transporter"
#else
#define MODULE_NAME "amsample_SA"
#define ENVIRONMENT "Teradata Standalone Utilities"
#endif
#define MODULE_VERS "17.10.00.00" /* SRC_ID */
/*#define TEST_TIMEOUT 1 */
/* Initialization string keywords */
#define MAX_PARMS 256 /* maximum init string parms accepted */
#define Help_KEYWORD "HELP"
/* Number of blocks to return */
#define BlockCount_KEYWORD "BLOCKCOUNT"
#define BlockCount_MAX 100000000
#define BlockCount_DEFAULT 10
/* Number of records returned per block */
#define RecordsPerBlock_KEYWORD "RECORDCOUNT"
#define RecordsPerBlock_MAX 100000
#define RecordsPerBlock_DEFAULT 10
/* Log file name */
#define Trace_KEYWORD "TRACE"
static char SG_ErrorText[pmiMAX_ETEXT_LEN+1];
static size_t SG_ErrorTextLen=0;
static pmTrceLvl_t SG_TraceLevel=pmTrceEvents;
static FILE *SG_AMlogFp=NULL;
static char AXMAttr_1[] = "AXSM AXM attribute #1 value";
static char FileAttr_1[] = "AXSM File attribute #1 value";
static unsigned long SG_BlocksToEOF;
static unsigned long SG_RecsPerBlock;
static char AMlogFName[pmiMAX_FNAME_LEN+1];
static long SG_TimeOutSeconds;
typedef struct _LogRec
{
pmUInt16 RecLength;
pmUInt16 Filler1;
pmUInt32 I_RecNum;
pmUInt32 I_block;
pmUInt32 I_Dummy;
pmUInt16 Filler2;
pmUInt16 I_charlen;
char V_char[7];
char EOR;
} LogRec_t;
#define MAX_MSGSTR_LEN 1024
#define TRACE_LOG_MAX_LENGTH MAX_MSGSTR_LEN+256
static char MsgStr[MAX_MSGSTR_LEN];
/* MACRO definitions */
#define TRCELOG(MsgTraceLevel,Format,variable) \
if ( SG_TraceLevel>=MsgTraceLevel ) \
{ \
char Trcetext[TRACE_LOG_MAX_LENGTH]; \
sprintf (Trcetext,Format,variable); \
AMlog(Trcetext); \
}
#define EXIT_FAILURE() \
SG_ErrorTextLen = strlen(SG_ErrorText); \
AMstdout(SG_ErrorText); \
return pmrcFailure;
#define CHECK_ARG_PRESENT(index) \
if ( index+1 >= argc )\
{\
sprintf (SG_ErrorText,"option %s: argument missing",argv[index]);\
EXIT_FAILURE();\
}\
if ( strlen(argv[index+1]) == 0 )\
{\
sprintf (SG_ErrorText,"option %s: argument missing",argv[index]);\
EXIT_FAILURE();\
}
***********************************************************************/
/* AMlog */
***********************************************************************/
static void AMlog ( char *str )
{
if ( SG_AMlogFp != NULL )
{
fprintf (SG_AMlogFp,"%s\n",str);
fflush (SG_AMlogFp);
}
return;
}
/***********************************************************************/
/* AMstdout */
/* (Access Module standard output) */
/* Used when trace file not open. */
/***********************************************************************/
static void AMstdout ( char *str )
{
/* If used with Teradata Parallel Transporter, */
/* stdout may by blocked (bit-bucket) */
/* Send all stdout to a predefined file. */
/* (could be a parameter) */
#if defined (TPT_VERSION)
#define AMstdoutFName "AMstdout.txt"
static FILE *AMstdoutFp=NULL;
if ( AMstdoutFp == NULL ) AMstdoutFp = fopen(AMstdoutFName,"w");
if ( AMstdoutFp != NULL )
{
fprintf (AMstdoutFp,"%s: %s\n",MODULE_NAME,str);
fflush (AMstdoutFp);
}
/* If used with Standalone Utilities, stdout is available */
#else
printf ( "%s: %s\n",MODULE_NAME,str );
#endif
AMlog(str); /* ALL stdout should be in log */
return;
}
/**********************************************************************/
/* ShowParms */
/* Display AM parameters */
/**********************************************************************/
#undef CurrentFunction
#define CurrentFunction "ShowParms"
static void ShowParms ( )
{
AMstdout("Parameters:");
/* Help */
sprintf(MsgStr,"%s: Show this information\n\tsyntax %s",
Help_KEYWORD,Help_KEYWORD);
AMstdout(MsgStr);
/* BLOCKCOUNT <value> */
sprintf(MsgStr,"%s: %s\n\t%s\n\tsyntax: %s %s %d\n\t%s %d",
BlockCount_KEYWORD,
"Specifies the number of record blocks to return.",
"When this value has been satisfied, an end-of-file will be returned.",
BlockCount_KEYWORD,
"<count> where <count> is within the range of 1 to",
BlockCount_MAX,
"the default is",
BlockCount_DEFAULT);
AMstdout(MsgStr);
/* RECORDCOUNT <value> */
sprintf(MsgStr,"%s: %s\n\tsyntax: %s %s %d\n\t%s %d",
RecordsPerBlock_KEYWORD,
"Specifies the number of records returned in each block.",
RecordsPerBlock_KEYWORD,
"<count> where <count> is within the range of 1 to",
RecordsPerBlock_MAX,
"the default is",
RecordsPerBlock_DEFAULT);
AMstdout(MsgStr);
/* TRACE <filename> <tracelevel> */
sprintf(MsgStr,"%s: %s\n\tsyntax: %s %s \n\t%s \n\t%s %d and %d",
Trace_KEYWORD,
"Specifies both the filename and trace level for the log",
Trace_KEYWORD,
"<filename> <tracelevel>",
"where <filename> is any valid file system object",
"and <tracelevel> is between",
pmTrceNone,pmTrceInfo);
AMstdout(MsgStr);
return;
}
/**********************************************************************/
/* ParseParms */
/* parse init string */
/**********************************************************************/
#undef CurrentFunction
#define CurrentFunction "ParseParms"
static pmReturnType ParseParms ( pmiInit_t* Parms )
{
char *pParameter;
int i, j, ipos, ioffs, rc;
pmReturnType retcode;
char *argv[MAX_PARMS];
int argc;
int initstrl;
int bUseParmFile = 0;
if ((initstrl = Parms->InitStrL) > 0) pParameter = Parms->InitStr;
else
{
sprintf(SG_ErrorText,"!ERROR! Empty initialization string");
EXIT_FAILURE();
}
/* =================================== convert initstr to argc argv */
ipos = ioffs = 0;
argc = 0;
for (i=0;i<MAX_PARMS;i++) argv[i] = 0;
while (ipos < initstrl)
{
/* get offset to next non-whitespace */
ioffs = strspn(&pParameter[ipos]," \n\t\r\f");
ipos = ipos + ioffs;
if (ipos >= initstrl) break;
/* get offset to next whitespace */
ioffs = strcspn(&pParameter[ipos]," \n\t\r\f\0");
if ( argc > MAX_PARMS-1 )
{
sprintf(SG_ErrorText,"Too many initialization string parameters");
EXIT_FAILURE();
}
argv[argc] = (char*)malloc(ioffs+1);
strncpy(argv[argc],&(pParameter[ipos]),ioffs);
memcpy(argv[argc]+(ioffs),"\0",1);
ipos = ipos+ioffs;
argc++;
}
if ( argc < 1 )
{
sprintf(SG_ErrorText,"Empty initialization string");
EXIT_FAILURE();
}
argv[argc] = 0;
SG_BlocksToEOF = 0;
SG_RecsPerBlock = 0;
AMlogFName[0] = '\0';
SG_TraceLevel = pmTrceNone;
/* ============================ process initstr arguments and values */
i=0;
retcode = pmrcOK;
do
{
int bValidKeywordFound = 0;
char KeyWord[100];
for (j=0;j<strlen(argv[i]);j++) argv[i][j] = toupper(argv[i][j]);
strcpy(KeyWord,argv[i]);
sprintf(MsgStr,"Parameter Keyword: '%s'",KeyWord);
AMstdout(MsgStr);
if ( !strcmp(KeyWord,Help_KEYWORD) )
{
ShowParms();
bValidKeywordFound = 1;
i++;
}
if ( !strcmp(KeyWord,BlockCount_KEYWORD) )
{
CHECK_ARG_PRESENT (i);
SG_BlocksToEOF = atol (argv[i+1]);
if ( SG_BlocksToEOF > BlockCount_MAX ||
SG_BlocksToEOF < 1 )
{
sprintf SG_ErrorText,"Invalid '%s' keyword value (%d). %s %d",
KeyWord,SG_BlocksToEOF,
"Valid range is 1 to",BlockCount_MAX);
EXIT_FAILURE();
}
bValidKeywordFound = 1;
i = i + 2;
}
if ( !strcmp(KeyWord,RecordsPerBlock_KEYWORD) )
{
CHECK_ARG_PRESENT (i);
SG_RecsPerBlock = atol (argv[i+1]);
if ( SG_RecsPerBlock > RecordsPerBlock_MAX ||
SG_RecsPerBlock < 1 )
{
sprintf (SG_ErrorText,"Invalid '%s' keyword value (%d). %s %d",
KeyWord,SG_RecsPerBlock,
"Valid range is 1 to",RecordsPerBlock_MAX);
EXIT_FAILURE();
}
bValidKeywordFound = 1;
i = i + 2;
}
if ( !strcmp(KeyWord,Trace_KEYWORD) )
{
CHECK_ARG_PRESENT (i);
if ( strlen(argv[i+1]) > pmiMAX_FNAME_LEN )
{
sprintf (SG_ErrorText,"Invalid '%s' keyword value (%s). %s %d",
KeyWord,argv[i+1],
"Maximum length is",pmiMAX_FNAME_LEN );
EXIT_FAILURE();
}
strcpy(AMlogFName,argv[i+1]);
if ( argc < i+2 )
{
sprintf (SG_ErrorText,"Keyword '%s' %s (trace level) expected",
KeyWord,"second parmameter");
EXIT_FAILURE();
}
SG_TraceLevel = atol (argv[i+2]);
if ( SG_TraceLevel < pmTrceNone || SG_TraceLevel> pmTrceInfo )
{
sprintf (SG_ErrorText,"Invalid '%s' %s (%d). %s %d to %d",
KeyWord,"keyword value",SG_TraceLevel,
"Valid range is",pmTrceNone,pmTrceInfo);
EXIT_FAILURE();
}
bValidKeywordFound = 1;
i = i + 3;
}
if ( !bValidKeywordFound )
{
sprintf(MsgStr,"Keyword '%s' ignored - not recognized",KeyWord);
AMstdout(MsgStr);
i++;
}
} while ( i<argc && retcode == pmrcOK );
/* free up memory */
for (i=0;i<MAX_PARMS;i++) {if (argv[i] != 0) free(argv[i]);}
/* =============== Confirm that required parameters have been defined */
/* and display parameters in effect */
if ( !SG_BlocksToEOF )
{
SG_BlocksToEOF = BlockCount_DEFAULT;
sprintf(MsgStr,"Keyword '%s' not provided. %s.",BlockCount_KEYWORD,
"It's value will be set to the default");
AMstdout(MsgStr);
}
sprintf(MsgStr,"Keyword '%s' value defined as %d.",
BlockCount_KEYWORD,SG_BlocksToEOF);
AMstdout(MsgStr);
if ( !SG_RecsPerBlock )
{
SG_RecsPerBlock = RecordsPerBlock_DEFAULT;
sprintf(MsgStr,"Keyword '%s' not provided. %s.",RecordsPerBlock_KEYWORD,
"It's value will be set to the default");
AMstdout(MsgStr);
}
sprintf(MsgStr,"Keyword '%s' value defined as %d.",
RecordsPerBlock_KEYWORD,SG_RecsPerBlock);
AMstdout(MsgStr);
if ( strlen(AMlogFName) )
{
sprintf(MsgStr,"Keyword '%s' value defined as '%s' '%d'",
Trace_KEYWORD,AMlogFName,SG_TraceLevel);
}
else sprintf(MsgStr,"Keyword '%s' not defined",Trace_KEYWORD);
AMstdout(MsgStr);
return pmrcOK;
}
/****************************************************************************/
/****************************************************************************/
/* Main routine */
/****************************************************************************/
/****************************************************************************/
#ifdef WIN32
__declspec(dllexport)
#endif
void PIDMMain ( pmiCmdBlock_t *Opts, void *OptParms )
{
pmReturnType retcode=pmrcOK;
static pmUInt32 SG_BufferLen;
static pmUInt32 SG_rec_cnt;
static pmUInt32 SG_block_cnt;
static LogRec_t SG_LogicalRecords[RecordsPerBlock_MAX];
pmUInt32 i;
pmUInt16 RecLength;
char *cptr;
static bHeadersAnnounced = 0;
char AtrName[pmMAX_ATR_NAME_LEN+1];
/* Announce which version of the header files were used */
/* at compile time. If the wrong headers, or packing option, */
/* were used, everything goes south without explanation. */
/* We do this before any of the parameters are referenced. */
/* So, if things go awry, we'll know if this was the problem. */
if ( !bHeadersAnnounced )
{
AMstdout(PM_COPYRIGHT_NOTICE);
sprintf ( MsgStr,"Sample Access Module ('%s') Version: %s.",
MODULE_NAME,MODULE_VERS);
AMstdout(MsgStr);
sprintf (MsgStr,"Compiled for %s (%s).",PLATFORM_ID,ENVIRONMENT);
AMstdout(MsgStr);
AMstdout(pmdcomt_ID);
AMstdout(pmddamt_ID);
bHeadersAnnounced = 1;
}
/****************************************************************************/
/* This is the main decision block */
/* Specific action taken is determined by the value */
/* of the Reqtype field in the Opts parameter */
/****************************************************************************/
switch (Opts->Reqtype) /* switch on request type */
{
/*--------------------------------------------------------------------------*/
/* AXSM Initialization */
/*--------------------------------------------------------------------------*/
case pmiPIDMOptInit:
TRCELOG(pmTrceInfo,"%s","Entry pmiPIDMOptInit");
/* Make sure the the headers used by the DataConnector */
/* are the same versions that this AXSM used */
/* when compiling! */
if ( ((pmiInit_t*)OptParms)->InterfaceVerNo != pmInterfaceVersionD
|| ((pmiInit_t*)OptParms)->InterfaceVerNoD != pmiInterfaceVersion )
retcode = pmrcBadVer;
/* Set that all important AXSM identifying void pointer */
/* that the AXSM can use for anything */
((pmiInit_t*)OptParms)->PIData = 0;
/* Examine init string */
retcode = ParseParms( (pmiInit_t*)OptParms );
if ( retcode ) break;
if ( SG_TraceLevel > pmTrceNone )
{
SG_AMlogFp = fopen(AMlogFName,"w");
if ( SG_AMlogFp == NULL ) AMstdout("Trace log file open failed!");
}
AMlog(PM_COPYRIGHT_NOTICE);
sprintf (MsgStr,"Sample Access Module ('%s') Version: %s.",
MODULE_NAME,MODULE_VERS);
AMlog(MsgStr);
sprintf (MsgStr,"Compiled for %s (%s).",PLATFORM_ID,ENVIRONMENT);
AMlog(MsgStr);
AMlog(pmdcomt_ID);
AMlog(pmddamt_ID);
switch ( SG_TraceLevel )
{
case pmTrceNone:
sprintf (MsgStr,"Trace level set to 'None' (%d)",pmTrceNone);
break;
case pmTrceEvents:
sprintf (MsgStr,"Trace level set to 'Events' (%d)",
pmTrceEvents);
break;
case pmTrceIOcounts:
sprintf (MsgStr,"Trace level set to 'IOcounts' (%d)",
pmTrceIOcounts);
break;
case pmTrceIObufs:
sprintf (MsgStr,"Trace level set to 'IObufs' (%d)",
pmTrceIObufs);
break;
case pmTrceInfo:
sprintf (MsgStr,"Trace level set to 'Info' (%d)",pmTrceInfo);
break;
default:
sprintf (MsgStr,"%s (%d) %s (%d)",
"Invalid trace level",SG_TraceLevel,
"reset to 'Events'",pmTrceEvents);
SG_TraceLevel = pmTrceEvents;
}
AMlog(MsgStr);
sprintf (MsgStr,"AM will provide %d blocks of %d records each %s",
SG_BlocksToEOF,SG_RecsPerBlock,
"in 'FastLoad' format (pmIDFBin1Plus)");
AMstdout(MsgStr);
break;
/*--------------------------------------------------------------------------*/
/* File Open */
/*--------------------------------------------------------------------------*/
case pmiPIDMOptOpen:
TRCELOG(pmTrceInfo,"%s","Entry pmiPIDMOptOpen");
SG_block_cnt = 0; /* set 'blocks read' to zero */
SG_BufferLen = 0; /* Initialize 'actual' buffer length */
SG_rec_cnt = 0; /* set 'records generated' to zero */
/* Fill in 'SG_LogicalRecords' for subsequent reads */
/* Format as 'text' data (trailing EOR byte) */
RecLength = sizeof(SG_LogicalRecords[0]) -
sizeof(SG_LogicalRecords[0].RecLength) -
sizeof(SG_LogicalRecords[0].EOR);
for (i=0;i<SG_RecsPerBlock;i++)
{
SG_LogicalRecords[i].RecLength = RecLength;
SG_LogicalRecords[i].I_RecNum = 0;
SG_LogicalRecords[i].I_block = 1;
SG_LogicalRecords[i].I_Dummy = 222;
SG_LogicalRecords[i].I_charlen = 7;
strcpy(SG_LogicalRecords[i].V_char,"XasciiX");
SG_LogicalRecords[i].EOR = 0x0a;
}
SG_BufferLen = SG_RecsPerBlock*sizeof(SG_LogicalRecords[0]);
/* Fill in device max block size, internal header length */
/* and that all important file identifying void pointer */
/* that the Access Module can use for anything */
((pmiOpen_t*)OptParms)->BlkSize = SG_BufferLen;
((pmiOpen_t*)OptParms)->BlkHeaderLen = 0;
((pmiOpen_t*)OptParms)->FIData = 0;
break;
/*--------------------------------------------------------------------------*/
/* File Close */
/*--------------------------------------------------------------------------*/
case pmiPIDMOptClose:
case pmiPIDMOptCloseR:
TRCELOG(pmTrceInfo,"%s","Entry pmiPIDMOptClose[R]");
break;
/*--------------------------------------------------------------------------*/
/* Read */
/*--------------------------------------------------------------------------*/
case pmiPIDMOptRead:
TRCELOG(pmTrceInfo,"%s","Entry pmiPIDMOptRead");
/* EOF? */
SG_block_cnt++;
if ( SG_block_cnt > SG_BlocksToEOF )
{
TRCELOG(pmTrceEvents,"%s","End-of-File");
((pmiRW_t*)OptParms)->BufferLen = 0;
retcode = pmrcEOF;
break;
}
#ifdef TEST_TIMEOUT
if ( SG_block_cnt > 1 )
{
TRCELOG(pmTrceEvents,"%s","Arbitrary timeout");
((pmiRW_t*)OptParms)->BufferLen = 0;
retcode = pmrcTimeout;
break;
}
#endif
/* Update MyBuffer for this read */
for (i=0;i<SG_RecsPerBlock;i++)
{
SG_rec_cnt++;
SG_LogicalRecords[i].I_RecNum = SG_rec_cnt;
SG_LogicalRecords[i].I_block = SG_block_cnt;
}
/* Copy generated block to DataConnector buffer */
memcpy( ((pmiRW_t*)OptParms)->Buffer,SG_LogicalRecords,SG_BufferLen);
/* Return the record length */
((pmiRW_t*)OptParms)->BufferLen = SG_BufferLen;
if ( SG_AMlogFp != NULL )
{
TRCELOG(pmTrceInfo,"%s","calling amHexDmp() for local copy");
amHexDmp ( SG_AMlogFp,(char *)SG_LogicalRecords,
(unsigned)SG_BufferLen,"i->",1);
TRCELOG(pmTrceInfo,"%s","calling amHexDmp() for interface copy");
amHexDmp ( SG_AMlogFp,(char *)((pmiRW_t*)OptParms)->Buffer,
(unsigned)((pmiRW_t*)OptParms)->BufferLen,"x->",1);
}
TRCELOG(pmTrceInfo,"%s","Exit pmiPIDMOptRead");
break;
/*--------------------------------------------------------------------------*/
/* Get and Put Access Module or File attributes */
/*--------------------------------------------------------------------------*/
case pmiPIDMOptGetA_A:
TRCELOG(pmTrceInfo,"%s","Entry pmiPIDMOptGetA_A");
strcpy (AtrName,((pmiAttr_t*)OptParms)->AttrName);
if ( strcmp(AtrName,"AXMAttribute#1") )
{
sprintf(MsgStr,"Attribute '%s' not recognized. %s",
AtrName,"Value can not be supplied");
retcode = pmrcBadAttrName;
}
else
{
sprintf(MsgStr,"Attribute '%s' recognized. %s '%s' returned",
AtrName,"Value",AXMAttr_1);
strcpy(&((pmiAttr_t*)OptParms)->AttrValue[0],AXMAttr_1);
((pmiAttr_t*)OptParms)->AttrValueLen = strlen(AXMAttr_1);
}
break;
case pmiPIDMOptGetF_A:
TRCELOG(pmTrceInfo,"%s","Entry pmiPIDMOptGetF_A");
strcpy (AtrName,((pmiAttr_t*)OptParms)->AttrName);
if ( strcmp(AtrName,"FileAttribute#1") )
{
sprintf(MsgStr,"Attribute '%s' not recognized. %s",
AtrName,"Value can not be supplied");
retcode = pmrcBadAttrName;
}
else
{
sprintf(MsgStr,"Attribute '%s' recognized. %s '%s' returned",
AtrName,"Value",FileAttr_1);
strcpy(&((pmiAttr_t*)OptParms)->AttrValue[0],FileAttr_1);
((pmiAttr_t*)OptParms)->AttrValueLen = strlen(FileAttr_1);
}
AMstdout(MsgStr);
break;
/* Handle/receive attributes with Access Module scope */
case pmiPIDMOptPutA_A:
TRCELOG(pmTrceInfo,"%s","Entry pmiPIDMOptPutA_A");
strcpy (AtrName,((pmiAttr_t*)OptParms)->AttrName);
sprintf (MsgStr,"Received AXSMOD attribute '%s'",AtrName);
TRCELOG(pmTrceEvents,"%s",MsgStr);
sprintf (MsgStr,"Checking for valid %s attributes",ENVIRONMENT);
TRCELOG(pmTrceEvents,"%s",MsgStr);
/* TPT_VERSION symbol */
/* tells us that we're compiling for use with the */
/* Teradata Parallel Transporter environment */
#ifdef TPT_VERSION
{
#include "pxoper.h"
PX_OperatorHandle operatorHandle;
char *cPtr;
PX_Length PX_Len;
PXSTC_Code PX_rc;
/* TPT operator handle */
#define MY_TPT_DC_ATTR_VALUE "SAMPLE_ATTR_CHAR_VALUE"
#define AM_ATTR_TPT_DCOP_AM_NAME "AccessModuleName"
if ( strcmp(AtrName,PM_ATR_TPT_OP_HANDLE))
{
sprintf (MsgStr,"Rejected attribute: '%s'",AtrName);
AMstdout(MsgStr);
retcode = pmrcBadAttrName;
break;
}
sprintf (MsgStr,"Recognized attribute: '%s'",AtrName);
AMstdout(MsgStr);
memcpy((char*)&operatorHandle,((pmiAttr_t*)OptParms)->AttrValue,
((pmiAttr_t*)OptParms)->AttrValueLen);
sprintf(MsgStr,"%s: operatorHandle=x'%x'",MODULE_NAME,operatorHandle);
TRCELOG(pmTrceEvents,"%s",MsgStr);
/* With the Teradata Parallel Transporter operator handle, */
/* All the TPT DataConnector operator attributes are available. */
/* First, we get the Access Module name attribute. This attribute */
/* is the name of this module and must have existed in order to */
/* get this Access Module running. */
/* The symbol AM_ATTR_TPT_DCOP_AM_NAME is defined in pxoper.h */
sprintf (MsgStr,"Retrieving attribute '%s'",AM_ATTR_TPT_DCOP_AM_NAME);
AMstdout(MsgStr);
PX_rc = PX_GetAttribute(operatorHandle,
AM_ATTR_TPT_DCOP_AM_NAME,
(PX_AttributeValue*)&cPtr,&PX_Len);
if ( PX_rc == PX_NotFound )
sprintf (MsgStr,"Attribute '%s' not found.",
AM_ATTR_TPT_DCOP_AM_NAME);
else if ( PX_rc )
sprintf (MsgStr,"PX_GetAttribute failed, rc=%d",
AM_ATTR_TPT_DCOP_AM_NAME);
else sprintf (MsgStr,"Retrieved attribute value '%s'",cPtr);
AMstdout(MsgStr);
/* The symbol MY_TPT_DC_ATTR_VALUE is defined within this Access Module. */
/* As it is used here, it is a VARCHAR and appears in the DataConnector's */
/* attribute definition list as: */
/* VARCHAR SAMPLE_ATTR_CHAR_VALUE, */
sprintf (MsgStr,"Retrieving attribute '%s'",MY_TPT_DC_ATTR_VALUE);
AMstdout(MsgStr);
PX_rc = PX_GetAttribute(operatorHandle,
MY_TPT_DC_ATTR_VALUE,
(PX_AttributeValue*)&cPtr,&PX_Len);
if ( PX_rc == PX_NotFound )
sprintf (MsgStr,"Attribute '%s' not found.",MY_TPT_DC_ATTR_VALUE);
else if ( PX_rc )
sprintf (MsgStr,"PX_GetAttribute failed, rc=%d",
MY_TPT_DC_ATTR_VALUE,PX_rc);
else sprintf (MsgStr,"Retrieved attribute value '%s'",cPtr);
AMstdout(MsgStr);
}
#else
/* Handle attributes received from the standalone utilities */
{
/* ATTRIBUTE DEFINES SHOULD (but do not have to) BE IN HEADER */
/* pmdcomt.h - available to AMs and DC clients */
if (!strcmp(AtrName,PM_ATR_NAME_TIMEOUT))
{
char AtrValue[100];
strcpy (AtrValue,((pmiAttr_t*)OptParms)->AttrValue);
SG_TimeOutSeconds = atol (AtrValue);
sprintf (MsgStr,"Recognized attribute: '%s' = %d seconds",
AtrName,SG_TimeOutSeconds);
}
else if (!strcmp(AtrName,PM_ATR_NAME_CHARSET_NAME) ||
!strcmp(AtrName,PM_ATR_NAME_CHARSET_NUMBER) ||
!strcmp(AtrName,PM_ATR_NAME_WR_BOM) ||
!strcmp(AtrName,PM_ATR_NAME_BYTE_ORDER) )
{
sprintf (MsgStr,"Recognized attribute: '%s' %s",
AtrName,"(no action taken)");
}
else
{
sprintf (MsgStr,"Unrecognized attribute: '%s'",AtrName);
retcode = pmrcBadAttrName;
}
AMstdout(MsgStr);
}
#endif
break;
case pmiPIDMOptPutF_A:
TRCELOG(pmTrceInfo,"%s","Entry pmiPIDMOptPutF_A");
strcpy (AtrName,((pmiAttr_t*)OptParms)->AttrName);
sprintf (MsgStr,"Received FILE attribute '%s'",AtrName);
TRCELOG(pmTrceEvents,"%s",MsgStr);
if ( !strcmp( AtrName,"FileAttribute#1") )
{
sprintf (MsgStr,"Recognized attribute: '%s' %s",
AtrName,"(no action taken)");
}
else
{
sprintf (MsgStr,"Unrecognized attribute: '%s'",AtrName);
retcode = pmrcBadAttrName;
}
AMstdout(MsgStr);
break;
/*--------------------------------------------------------------------------*/
/* Access Module shutdown */
/*--------------------------------------------------------------------------*/
case pmiPIDMOptShut:
TRCELOG(pmTrceInfo,"%s","Entry pmiPIDMOptShut");
/* If any files are currently open, close them */
retcode = pmrcOK;
break;
/*--------------------------------------------------------------------------*/
/* Access Module identification */
/*--------------------------------------------------------------------------*/
case pmiPIDMOptID:
TRCELOG(pmTrceInfo,"%s","Entry pmiPIDMOptID");
/* Supply the single module name for this Access Module identification */
/* If more modules are added, their identifying information */
/* must be appended to the list via VerIDList.Next */
strcpy( ((pmiID_t*)OptParms)->VerIDList.ModuleName,MODULE_NAME);
strcpy( ((pmiID_t*)OptParms)->VerIDList.ModuleVers,MODULE_VERS);
((pmiID_t*)OptParms)->VerIDList.Next = 0;
break;
/*--------------------------------------------------------------------------*/
/* NULL ops for checkpoint */
/*--------------------------------------------------------------------------*/
case pmiPIDMOptGetPos:
case pmiPIDMOptSetPos:
break;
default:
/* Handle unknown request type */
retcode = pmrcUnsupported;
} /* end switch on request type */
/* Insert the established return code into the command block */
/* for return DataConnector */
Opts->Retcode = retcode;
/* If there's a Access Module specific error, indicated by a return code */
/* of pmrcFailure, insert the associated error text into */
/* the command block for return to the DataConnector */
if ( retcode == pmrcFailure )
{
Opts->ErrMsg.Data = &SG_ErrorText[0];
Opts->ErrMsg.DataLength = SG_ErrorTextLen;
}
else
{
Opts->ErrMsg.Data = 0;
Opts->ErrMsg.DataLength = 0;
}
sprintf(MsgStr,"Returnning retcode=%d",retcode);
if ( retcode )
{ TRCELOG(pmTrceEvents,"%s",MsgStr); }
else
{ TRCELOG(pmTrceInfo,"%s",MsgStr); }
return;
}