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) int _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); }