Sample Notify Exit Routine
The following is the listing of tldnfyxt.c, the sample notify exit routine that is provided with Teradata TPump software.
/**************************************************************************
* *
* tldnfyxt.c - Sample Notify Exit for TPump. *
* *
* Copyright 1997-2013 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 - This is a sample notify exit for TPump. *
* *
* Execute - Build Notify on a Unix system *
* compile and link into shared object *
* cc -G tldnfyxt.c - o libtldnfyxt.so *
* - Build Notify on a Win32 system *
* compile and link into dynamic link library *
* cl /DWIN32 /LD tldnfyxt.c *
* - Build Notify on AIX system *
* cc -c -brtl -qalign=packed tldnfyxt.c *
* ld -G -e_dynamn -bE:export_dynamn.txt tldnfyxt.o *
* -o libtldnfyxt.so -lm -lc *
* where export_dynamn.txt conaints the symbol "_dynamn" *
* - Build Notify on Linux system *
* gcc -shared -fPIC tldnfyxt.c -o libtldnfyxt.so *
* *
**************************************************************************/
#ifdef __MVS__
#pragma pack(1)
#endif
#include <stdio.h>
typedef unsigned int UInt32;
typedef int Int32;
#define NOTIFYID_FASTLOAD 1
#define NOTIFYID_MULTILOAD 2
#define NOTIFYID_FASTEXPORT 3
#define NOTIFYID_BTEQ 4
#define NOTIFYID_TPUMP 5
#define MAXVERSIONIDLEN 32
#define MAXUTILITYNAMELEN 36
#define MAXUINT64LEN 24
#define MAXUSERNAMELEN 64
#define MAXUSERSTRLEN 80
#define MAXFILENAMELEN 256
typedef enum {
NMEventInitialize = 0,
NMEventFileInmodOpen = 1,
NMEventCkptBeg = 2,
NMEventImportBegin = 3,
NMEventImportEnd = 4,
NMEventErrorTable = 5,
NMEventDBSRestart = 6,
NMEventCLIError = 7,
NMEventDBSError = 8,
NMEventExit = 9,
NMEventTableStats = 10,
NMEventCkptEnd = 11,
NMEventRunStats = 12,
NMEventDMLError = 13,
NMEventCkptBeg64 = 14,
NMEventCkptEnd64 = 15,
NMEventImportEnd64 = 16,
NMEventErrorTable64 = 17,
NMEventTableStats64 = 18,
NMEventRunStats64 = 19,
NMEventDMLError64 = 20,
NMEventInitializeEON = 21
} NfyTLDEvent;
#define TIDUPROW 2816
typedef enum {
DEFeedbackDefault = 0,
DEFeedbackNoLogging = 1
} DMLErrorFeedbackType;
typedef struct _TLNotifyExitParm {
UInt32 Event; /* should be NfyFLDEvent values */
union {
struct {
int VersionLen;
char VersionId[MAXVERSIONIDLEN];
int UtilityId;
int UtilityNameLen;
char UtilityName[MAXUTILITYNAMELEN];
int UserNameLen;
char UserName[MAXUSERNAMELEN];
int UserStringLen;
char UserString[MAXUSERSTRLEN];
} Initialize;
struct {
int VersionLen;
char VersionId[MAXVERSIONIDLEN];
int UtilityId;
int UtilityNameLen;
char UtilityName[MAXUTILITYNAMELEN];
int UserNameLen;
char *UserName;
int UserStringLen;
char *UserString;
} InitializeEON;
struct {
int nImport;
} ImpStart;
struct { /*DR51679 added communication data structure*/
UInt32 FileNameLen; /* for file open event */
char FileOrInmodName[MAXFILENAMELEN];
UInt32 nImport;
} FileOpen ;
struct {
UInt32 Records;
} CheckPt;
struct {
char *TableName;
UInt32 Rows;
} ETDrop ;
struct {
Int32 ReturnCode;
} Exit;
struct {
int nImport;
UInt32 RecsIn;
UInt32 RecsSkipped;
UInt32 RecsRejd;
UInt32 RecsOut;
UInt32 RecsError;
} Complete;
struct {
char type;
char *dbasename;
char *szName;
UInt32 Activity;
} TableStats;
struct {
UInt32 ErrorCode;
} DBSError;
struct {
UInt32 ErrorCode;
} CLIError;
struct {
int nImport;
UInt32 nSQLstmt;
UInt32 nReqSent;
UInt32 RecsIn;
UInt32 RecsSkipped;
UInt32 RecsRejd;
UInt32 RecsOut;
UInt32 RecsError;
} Stats;
struct {
UInt32 nImport;
UInt32 ErrorCode;
char *ErrorMsg;
UInt32 nRecord;
unsigned char nApplySeq;
unsigned char nDMLSeq;
unsigned char nSMTSeq;
char *ErrorData;
UInt32 ErrorDataLen;
UInt32 *feedback;
} DMLError;
struct {
char Records[MAXUINT64LEN];
} CheckPt64;
struct {
UInt32 nImport;
UInt32 ErrorCode;
char *ErrorMsg;
char nRecord[MAXUINT64LEN];
unsigned char nApplySeq;
unsigned char nDMLSeq;
unsigned char nSMTSeq;
char *ErrorData;
UInt32 ErrorDataLen;
UInt32 *feedback;
} DMLError64;
struct {
char *TableName;
char Rows[MAXUINT64LEN];
} ETDrop64 ;
struct {
int nImport;
char RecsIn[MAXUINT64LEN];
char RecsSkipped[MAXUINT64LEN];
char RecsRejd[MAXUINT64LEN];
char RecsOut[MAXUINT64LEN];
char RecsError[MAXUINT64LEN];
} Complete64;
struct {
char type;
char *dbasename;
char *szName;
char Activity[MAXUINT64LEN];
} TableStats64;
struct {
int nImport;
UInt32 nSQLstmt;
UInt32 nReqSent;
char RecsIn[MAXUINT64LEN];
char RecsSkipped[MAXUINT64LEN];
char RecsRejd[MAXUINT64LEN];
char RecsOut[MAXUINT64LEN];
char RecsError[MAXUINT64LEN];
} Stats64;
} Vals;
} TLNotifyExitParm;
#ifdef I370
#define TLNfyExit MLNfEx
#endif
extern Int32 TLNfyExit(
#ifdef __STDC__
TLNotifyExitParm *Parms
#endif
);
#ifdef WIN32
__declspec(dllexport) long _dynamn(TLNotifyExitParm *P)
#else
Int32 _dynamn(P)
TLNotifyExitParm *P;
#endif
{
FILE *fp;
int i;
if (!(fp = fopen("NFYEXIT.OUT", "a")))
return(1);
switch(P->Event) {
case NMEventInitialize :
fprintf(fp, "exit called @ Tpump init.\n");
fprintf(fp, "Version: %s\n", P->Vals.Initialize.VersionId);
#ifdef __MVS__
P->Vals.Initialize.UtilityName[MAXUTILITYNAMELEN-1] = '\0';
#else
P->Vals.Initialize.UtilityName[MAXUTILITYNAMELEN] = '\0';
#endif
fprintf(fp, "Utility: %s\n", P->Vals.Initialize.UtilityName);
fprintf(fp, "User: %s\n", P->Vals.Initialize.UserName);
if (P->Vals.Initialize.UserStringLen)
fprintf(fp, "UserString: %s\n", P->Vals.Initialize.UserString);
break;
case NMEventInitializeEON :
fprintf(fp, "exit called @ Tpump init.\n");
fprintf(fp, "Version: %s\n", P->Vals.InitializeEON.VersionId);
#ifdef __MVS__
P->Vals.InitializeEON.UtilityName[MAXUTILITYNAMELEN-1] = '\0';
#else
P->Vals.InitializeEON.UtilityName[MAXUTILITYNAMELEN] = '\0';
#endif
fprintf(fp, "Utility: %s\n", P->Vals.InitializeEON.UtilityName);
fprintf(fp, "User: %s\n", P->Vals.InitializeEON.UserName);
if (P->Vals.InitializeEON.UserStringLen)
fprintf(fp, "UserString: %s\n", P->Vals.InitializeEON.UserString);
break;
case NMEventFileInmodOpen : /*DR51679 File Open Event added*/
fprintf(fp, "Exit called @ File/Inmod Open\n\
File/Inmod Name : %s Import : %d\n",
P->Vals.FileOpen.FileOrInmodName,P->Vals.FileOpen.nImport);
break;
case NMEventCkptBeg :
fprintf(fp,"exit called @ checkpoint begin : %u Records .\n",
P->Vals.CheckPt.Records);
break;
case NMEventCkptBeg64 :
fprintf(fp,"exit called @ checkpoint begin : %s Records .\n",
P->Vals.CheckPt64.Records);
break;
case NMEventCkptEnd :
fprintf(fp,"exit called @ checkpoint End : %u Records Sent.\n",
P->Vals.CheckPt.Records);
break;
case NMEventCkptEnd64 :
fprintf(fp,"exit called @ checkpoint End : %s Records Sent.\n",
P->Vals.CheckPt64.Records);
break;
case NMEventCLIError :
fprintf(fp, "exit called @ CLI error %d\n",
P->Vals.CLIError.ErrorCode);
break;
case NMEventErrorTable :
fprintf(fp,"exit called @ ErrTable Drop : "
"%u logable records.\n",
P->Vals.ETDrop.Rows);
break;
case NMEventErrorTable64 :
fprintf(fp,"exit called @ ErrTable Drop : "
"%s logable records.\n",
P->Vals.ETDrop64.Rows);
break;
case NMEventDBSError :
fprintf(fp, "exit called @ DBS error %d\n",
P->Vals.DBSError.ErrorCode);
break;
case NMEventImportBegin:
fprintf(fp, "exit called @ import %d starting. \n",
P->Vals.ImpStart.nImport);
break;
case NMEventImportEnd :
fprintf(fp, "exit called @ import %d ending \n",
P->Vals.Complete.nImport);
fprintf(fp,
"Total Records Read: %u \nRecords Skipped "
"%u \nUnreadable Records:%u \nRecords Sent: "
"%u \nData Errors : %u \n",
P->Vals.Complete.RecsIn,
P->Vals.Complete.RecsSkipped,
P->Vals.Complete.RecsRejd,
P->Vals.Complete.RecsOut,
P->Vals.Complete.RecsError);
break;
case NMEventImportEnd64 :
fprintf(fp, "exit called @ import %d ending \n",
P->Vals.Complete64.nImport);
fprintf(fp,
"Total Records Read: %s \n",
P->Vals.Complete64.RecsIn);
fprintf(fp,
"Records Skipped: %s \n",
P->Vals.Complete64.RecsSkipped);
fprintf(fp,
"Unreadable Records: %s \n",
P->Vals.Complete64.RecsRejd);
fprintf(fp,
"Records Sent: %s \n",
P->Vals.Complete64.RecsOut);
fprintf(fp,
"Data Errors: %s \n",
P->Vals.Complete64.RecsError);
break;
case NMEventDBSRestart :
fprintf(fp, "exit called @ RDBMS restarted\n");
break;
case NMEventExit :
fprintf(fp, "exit called @ tpump notify out of scope:"
" return code %d.\n",
P->Vals.Exit.ReturnCode);
break;
case NMEventTableStats:
fprintf(fp,"exit called @ Table Stats: \n");
if(P->Vals.TableStats.type == 'I')
fprintf(fp,"Rows Inserted : "
"%u \nTable/Macro Name : %s \nDatabase Name"
" : %s \n",
P->Vals.TableStats.Activity,
P->Vals.TableStats.szName,
P->Vals.TableStats.dbasename);
if(P->Vals.TableStats.type == 'U')
fprintf(fp,"Rows Updated : "
"%u \nTable/Macro Name : %s \nDatabase Name"
" : %s \n",
P->Vals.TableStats.Activity,
P->Vals.TableStats.szName,
P->Vals.TableStats.dbasename);
if(P->Vals.TableStats.type == 'D')
fprintf(fp,"Rows Deleted : "
"%u \nTable/Macro Name : %s \nDatabase Name"
" : %s \n",
P->Vals.TableStats.Activity,
P->Vals.TableStats.szName,
P->Vals.TableStats.dbasename);
break;
case NMEventTableStats64:
fprintf(fp,"exit called @ Table Stats: \n");
if(P->Vals.TableStats64.type == 'I')
fprintf(fp,"Rows Inserted : "
"%s \nTable/Macro Name : %s \nDatabase Name"
" : %s \n",
P->Vals.TableStats64.Activity,
P->Vals.TableStats64.szName,
P->Vals.TableStats64.dbasename);
if(P->Vals.TableStats64.type == 'U')
fprintf(fp,"Rows Updated : "
"%s \nTable/Macro Name : %s \nDatabase Name"
" : %s \n",
P->Vals.TableStats64.Activity,
P->Vals.TableStats64.szName,
P->Vals.TableStats64.dbasename);
if(P->Vals.TableStats64.type == 'D')
fprintf(fp,"Rows Deleted : "
"%s \nTable/Macro Name : %s \nDatabase Name"
" : %s \n",
P->Vals.TableStats64.Activity,
P->Vals.TableStats64.szName,
P->Vals.TableStats64.dbasename);
break;
case NMEventRunStats :
fprintf(fp, "exit called @ states\n");
fprintf(fp, "import %d \n",
P->Vals.Stats.nImport);
fprintf(fp,
"Total SQL Statements: %u \nRequest Sent: %u \n"
"Records Read: %u \nRecords Skipped: %u \n"
"nUnreadable Records: %u \nRecords Sent: %u \n"
"Data Errors : %u \n",
P->Vals.Stats.nSQLstmt,
P->Vals.Stats.nReqSent,
P->Vals.Stats.RecsIn,
P->Vals.Stats.RecsSkipped,
P->Vals.Stats.RecsRejd,
P->Vals.Stats.RecsOut,
P->Vals.Stats.RecsError);
break;
case NMEventRunStats64 :
fprintf(fp, "exit called @ states\n");
fprintf(fp, "import %d \n",
P->Vals.Stats64.nImport);
fprintf(fp,
"Total SQL Statements: %d \n",
P->Vals.Stats64.nSQLstmt);
fprintf(fp,
"Request Sent: %d \n",
P->Vals.Stats64.nReqSent);
fprintf(fp,
"Records Read: %s \n",
P->Vals.Stats64.RecsIn);
fprintf(fp,
"Records Skipped: %s \n",
P->Vals.Stats64.RecsSkipped);
fprintf(fp,
"Unreadable Records: %s \n",
P->Vals.Stats64.RecsRejd);
fprintf(fp,
"Records Sent: %s \n",
P->Vals.Stats64.RecsOut);
fprintf(fp,
"Data Errors: %s \n",
P->Vals.Stats64.RecsError);
break;
case NMEventDMLError :
fprintf(fp, "exit called @ DML error \n");
fprintf(fp, "import %d \n",
P->Vals.DMLError.nImport);
fprintf(fp,
"Error code: %u \nError text: %s \n"
"Record number: %u \nApply number: %d \n"
"DML number: %d \nStatement number: %d \n"
"Error data length : %u \n"
"feedback : %u \n",
P->Vals.DMLError.ErrorCode,
P->Vals.DMLError.ErrorMsg,
P->Vals.DMLError.nRecord,
P->Vals.DMLError.nApplySeq,
P->Vals.DMLError.nDMLSeq,
P->Vals.DMLError.nSMTSeq,
P->Vals.DMLError.ErrorDataLen,
*(P->Vals.DMLError.feedback));
fprintf(fp, "Error data: ");
for (i=0 ;i<P->Vals.DMLError.ErrorDataLen; i++) {
fprintf(fp, "%c", P->Vals.DMLError.ErrorData[i]);
}
fprintf(fp, "\n");
if (P->Vals.DMLError.ErrorCode == TIDUPROW) {
*(P->Vals.DMLError.feedback) = DEFeedbackNoLogging;
fprintf(fp, "Returning feedback = %u \n",
DEFeedbackNoLogging);
}
break;
case NMEventDMLError64 :
fprintf(fp, "exit called @ DML error \n");
fprintf(fp, "import %d \n",
P->Vals.DMLError64.nImport);
fprintf(fp,
"Error code: %u \nError text: %s \n"
"Record number: %s \nApply number: %d \n"
"DML number: %d \nStatement number: %d \n"
"Error data length : %u \n"
"feedback : %u \n",
P->Vals.DMLError64.ErrorCode,
P->Vals.DMLError64.ErrorMsg,
P->Vals.DMLError64.nRecord,
P->Vals.DMLError64.nApplySeq,
P->Vals.DMLError64.nDMLSeq,
P->Vals.DMLError64.nSMTSeq,
P->Vals.DMLError64.ErrorDataLen,
*(P->Vals.DMLError64.feedback));
fprintf(fp, "Error data: ");
for (i=0 ;i<P->Vals.DMLError64.ErrorDataLen; i++) {
fprintf(fp, "%c", P->Vals.DMLError64.ErrorData[i]);
}
fprintf(fp, "\n");
if (P->Vals.DMLError64.ErrorCode == TIDUPROW) {
*(P->Vals.DMLError64.feedback) = DEFeedbackNoLogging;
fprintf(fp, "Returning feedback = %u \n",
DEFeedbackNoLogging);
}
break;
default :
fprintf(fp,"\nAn Invalid Event Passed to the Exit Routine\n");
break;
}
fclose(fp);
return(0);
}