Sample C program for displaying events using an event monitor (amqsaiem.c)
The sample C program amqsaiem.c demonstrates a basic event monitor using the MQAI.
******************************************************************************/ /* */ /* Program name: AMQSAIEM.C */ /* */ /* Description: Sample C program to demonstrate a basic event monitor */ /* using the IBM MQ Admin Interface (MQAI). */ /* */ /* 63H9336 */ /* (c) Copyright IBM Corp. 1999, 2020. All Rights Reserved. */ /* */ /* disclosure restricted by GSA ADP Schedule Contract with */ /* IBM Corp. */ /******************************************************************************/ /* */ /* Function: */ /* AMQSAIEM is a sample C program that demonstrates how to write a simple */ /* event monitor using the mqGetBag call and other MQAI calls. */ /* */ /* The name of the event queue to be monitored is passed as a parameter */ /* to the program. This would usually be one of the system event queues:- */ /* SYSTEM.ADMIN.QMGR.EVENT Queue Manager events */ /* SYSTEM.ADMIN.PERFM.EVENT Performance events */ /* SYSTEM.ADMIN.CHANNEL.EVENT Channel events */ /* SYSTEM.ADMIN.LOGGER.EVENT Logger events */ /* */ /* To monitor the queue manager event queue or the performance event queue,*/ /* the attributes of the queue manager need to be changed to enable */ /* these events. For more information about this, see Part 1 of the */ /* Programmable System Management book. The queue manager attributes can */ /* be changed using either MQSC commands or the MQAI interface. */ /* Channel events are enabled by default. */ /* */ /* Program logic */ /* Connect to the Queue Manager. */ /* Open the requested event queue with a wait interval of 30 seconds. */ /* Wait for a message, and when it arrives get the message from the queue */ /* and format it into an MQAI bag using the mqGetBag call. */ /* There are many types of event messages and it is beyond the scope of */ /* this sample to program for all event messages. Instead the program */ /* prints out the contents of the formatted bag. */ /* Loop around to wait for another message until either there is an error */ /* or the wait interval of 30 seconds is reached. */ /* */ /******************************************************************************/ /* */ /* AMQSAIEM has 2 parameters - the name of the event queue to be monitored */ /* - the queue manager name (optional) */ /* */ /***************************************************************************** /******************************************************************************/ /* Includes */ /******************************************************************************/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <cmqc.h> /* MQI */ #include <cmqcfc.h> /* PCF */ #include <cmqbc.h> /* MQAI */ /******************************************************************************/ /* Macros */ /******************************************************************************/ #if MQAT_DEFAULT == MQAT_WINDOWS_NT #define Int64 "I64" #elif defined(MQ_64_BIT) #define Int64 "l" #else #define Int64 "ll" #endif /******************************************************************************/ /* Function prototypes */ /******************************************************************************/ void CheckCallResult(MQCHAR *, MQLONG , MQLONG); void GetQEvents(MQHCONN, MQCHAR *); int PrintBag(MQHBAG); int PrintBagContents(MQHBAG, int); /******************************************************************************/ /* Function: main */ /******************************************************************************/ int main(int argc, char *argv[]) { MQHCONN hConn; /* handle to connection */ MQCHAR QMName[MQ_Q_MGR_NAME_LENGTH+1]=""; /* default QM name */ MQLONG reason; /* reason code */ MQLONG connReason; /* MQCONN reason code */ MQLONG compCode; /* completion code */ /***************************************************************************/ /* First check the required parameters */ /***************************************************************************/ printf("Sample Event Monitor (times out after 30 secs)\n"); if (argc < 2) { printf("Required parameter missing - event queue to be monitored\n"); exit(99); } /**************************************************************************/ /* Connect to the queue manager */ /**************************************************************************/ if (argc > 2) strncpy(QMName, argv[2], (size_t)MQ_Q_MGR_NAME_LENGTH); MQCONN(QMName, &hConn, &compCode, &connReason); /***************************************************************************/ /* Report the reason and stop if the connection failed */ /***************************************************************************/ if (compCode == MQCC_FAILED) { CheckCallResult("MQCONN", compCode, connReason); exit( (int)connReason); } /***************************************************************************/ /* Call the routine to open the event queue and format any event messages */ /* read from the queue. */ /***************************************************************************/ GetQEvents(hConn, argv[1]); /***************************************************************************/ /* Disconnect from the queue manager if not already connected */ /***************************************************************************/ if (connReason != MQRC_ALREADY_CONNECTED) { MQDISC(&hConn, &compCode, &reason); CheckCallResult("MQDISC", compCode, reason); } return 0; } /******************************************************************************/ /* */ /* Function: CheckCallResult */ /* */ /******************************************************************************/ /* */ /* Input Parameters: Description of call */ /* Completion code */ /* Reason code */ /* */ /* Output Parameters: None */ /* */ /* Logic: Display the description of the call, the completion code and the */ /* reason code if the completion code is not successful */ /* */ /******************************************************************************/ void CheckCallResult(char *callText, MQLONG cc, MQLONG rc) { if (cc != MQCC_OK) printf("%s failed: Completion Code = %d : Reason = %d\n", callText, cc, rc); } /******************************************************************************/ /* */ /* Function: GetQEvents */ /* */ /******************************************************************************/ /* */ /* Input Parameters: Handle to the queue manager */ /* Name of the event queue to be monitored */ /* */ /* Output Parameters: None */ /* /* Logic: Open the event queue. */ /* Get a message off the event queue and format the message into */ /* a bag. */ /* A real event monitor would need to be programmed to deal with */ /* each type of event that it receives from the queue. This is */ /* outside the scope of this sample, so instead, the contents of */ /* the bag are printed. */ /* The program waits for 30 seconds for an event message and then */ /* terminates if no more messages are available. */ /* */ /******************************************************************************/ void GetQEvents(MQHCONN hConn, MQCHAR *qName) { MQLONG openReason; /* MQOPEN reason code */ MQLONG reason; /* reason code */ MQLONG compCode; /* completion code */ MQHOBJ eventQueue; /* handle to event queue */ MQHBAG eventBag = MQHB_UNUSABLE_HBAG; /* event bag to receive event msg */ MQOD od = {MQOD_DEFAULT}; /* Object Descriptor */ MQMD md = {MQMD_DEFAULT}; /* Message Descriptor */ MQGMO gmo = {MQGMO_DEFAULT}; /* get message options */ MQLONG bQueueOK = 1; /* keep reading msgs while true */ /***************************************************************************/ /* Create an Event Bag in which to receive the event. */ /* Exit the function if the create fails. */ /***************************************************************************/ mqCreateBag(MQCBO_USER_BAG, &eventBag, &compCode, &reason); CheckCallResult("Create event bag", compCode, reason); if (compCode !=MQCC_OK) return; /***************************************************************************/ /* Open the event queue chosen by the user */ /***************************************************************************/ strncpy(od.ObjectName, qName, (size_t)MQ_Q_NAME_LENGTH); MQOPEN(hConn, &od, MQOO_INPUT_AS_Q_DEF+MQOO_FAIL_IF_QUIESCING, &eventQueue, &compCode, &openReason); CheckCallResult("Open event queue", compCode, openReason); /***************************************************************************/ /* Set the GMO options to control the action of the get message from the */ /* queue. */ /***************************************************************************/ gmo.WaitInterval = 30000; /* 30 second wait for message */ gmo.Options = MQGMO_WAIT + MQGMO_FAIL_IF_QUIESCING + MQGMO_CONVERT; gmo.Version = MQGMO_VERSION_2; /* Avoid need to reset Message ID */ gmo.MatchOptions = MQMO_NONE; /* and Correlation ID after every */ /* mqGetBag /***************************************************************************/ /* If open fails, we cannot access the queue and must stop the monitor. */ /***************************************************************************/ if (compCode != MQCC_OK) bQueueOK = 0; /***************************************************************************/ /* Main loop to get an event message when it arrives */ /***************************************************************************/ while (bQueueOK) { printf("\nWaiting for an event\n"); /*************************************************************************/ /* Get the message from the event queue and convert it into the event */ /* bag. */ /*************************************************************************/ mqGetBag(hConn, eventQueue, &md, &gmo, eventBag, &compCode, &reason); /*************************************************************************/ /* If get fails, we cannot access the queue and must stop the monitor. */ /*************************************************************************/ if (compCode != MQCC_OK) { bQueueOK = 0; /*********************************************************************/ /* If get fails because no message available then we have timed out, */ /* so report this, otherwise report an error. */ /*********************************************************************/ if (reason == MQRC_NO_MSG_AVAILABLE) { printf("No more messages\n"); } else { CheckCallResult("Get bag", compCode, reason); } } /*************************************************************************/ /* Event message read - Print the contents of the event bag */ /*************************************************************************/ else { if ( PrintBag(eventBag) ) printf("\nError found while printing bag contents\n"); } /* end of msg found */ } /* end of main loop */ /***************************************************************************/ /* Close the event queue if successfully opened */ /***************************************************************************/ if (openReason == MQRC_NONE) { MQCLOSE(hConn, &eventQueue, MQCO_NONE, &compCode, &reason); CheckCallResult("Close event queue", compCode, reason); } /***************************************************************************/ /* Delete the event bag if successfully created. */ /***************************************************************************/ if (eventBag != MQHB_UNUSABLE_HBAG) { mqDeleteBag(&eventBag, &compCode, &reason); CheckCallResult("Delete the event bag", compCode, reason); } } /* end of GetQEvents */ /******************************************************************************/ /* */ /* Function: PrintBag */ /* */ /******************************************************************************/ /* */ /* Input Parameters: Bag Handle */ /* */ /* Output Parameters: None */ /* */ /* Returns: Number of errors found */ /* */ /* Logic: Calls PrintBagContents to display the contents of the bag. */ /* */ /***************************************************************************** int PrintBag(MQHBAG dataBag) { int errors; printf("\n"); errors = PrintBagContents(dataBag, 0); printf("\n"); return errors; } /******************************************************************************/ /* */ /* Function: PrintBagContents */ /* */ /******************************************************************************/ /* */ /* Input Parameters: Bag Handle */ /* Indentation level of bag */ /* */ /* Output Parameters: None */ /* */ /* Returns: Number of errors found */ /* */ /* Logic: Count the number of items in the bag */ /* Obtain selector and item type for each item in the bag. */ /* Obtain the value of the item depending on item type and display the */ /* index of the item, the selector and the value. */ /* If the item is an embedded bag handle then call this function again */ /* to print the contents of the embedded bag increasing the */ /* indentation level. */ /* */ /******************************************************************************/ int PrintBagContents(MQHBAG dataBag, int indent) { /***************************************************************************/ /* Definitions */ /***************************************************************************/ #define LENGTH 500 /* Max length of string to be read*/ #define INDENT 4 /* Number of spaces to indent */ /* embedded bag display */ /***************************************************************************/ /* Variables */ /***************************************************************************/ MQLONG itemCount; /* Number of items in the bag */ MQLONG itemType; /* Type of the item */ int i; /* Index of item in the bag */ MQCHAR stringVal[LENGTH+1]; /* Value if item is a string */ MQBYTE byteStringVal[LENGTH]; /* Value if item is a byte string */ MQLONG stringLength; /* Length of string value */ MQLONG ccsid; /* CCSID of string value */ MQINT32 iValue; /* Value if item is an integer */ MQINT64 i64Value; /* Value if item is a 64-bit */ /* integer */ MQLONG selector; /* Selector of item */ MQHBAG bagHandle; /* Value if item is a bag handle */ MQLONG reason; /* reason code */ MQLONG compCode; /* completion code */ MQLONG trimLength; /* Length of string to be trimmed */ int errors = 0; /* Count of errors found */ char blanks[] = " "; /* Blank string used to */ /* indent display */ /***************************************************************************/ /* Count the number of items in the bag */ /***************************************************************************/ mqCountItems(dataBag, MQSEL_ALL_SELECTORS, &itemCount, &compCode, &reason); if (compCode != MQCC_OK) errors++; else { printf(" printf(" printf(" } /***************************************************************************/ /* If no errors found, display each item in the bag */ /***************************************************************************/ if (!errors) { for (i = 0; i < itemCount; i++) { /********************************************************************/ /* First inquire the type of the item for each item in the bag */ /********************************************************************/ mqInquireItemInfo(dataBag, /* Bag handle */ MQSEL_ANY_SELECTOR, /* Item can have any selector*/ i, /* Index position in the bag */ &selector, /* Actual value of selector */ /* returned by call */ &itemType, /* Actual type of item */ /* returned by call */ &compCode, /* Completion code */ &reason); /* Reason Code */ if (compCode != MQCC_OK) errors++; switch(itemType) { case MQITEM_INTEGER: /***************************************************************/ /* Item is an integer. Find its value and display its index, */ /* selector and value. */ /***************************************************************/ mqInquireInteger(dataBag, /* Bag handle */ MQSEL_ANY_SELECTOR, /* Allow any selector */ i, /* Index position in the bag */ &iValue, /* Returned integer value &compCode, /* Completion code */ &reason); /* Reason Code */ if (compCode != MQCC_OK) errors++; else printf("%.*s %-2d %-4d (%d)\n", indent, blanks, i, selector, iValue); break case MQITEM_INTEGER64: /***************************************************************/ /* Item is a 64-bit integer. Find its value and display its */ /* index, selector and value. */ /***************************************************************/ mqInquireInteger64(dataBag, /* Bag handle */ MQSEL_ANY_SELECTOR, /* Allow any selector */ i, /* Index position in the bag */ &i64Value, /* Returned integer value */ &compCode, /* Completion code */ &reason); /* Reason Code */ if (compCode != MQCC_OK) errors++; else printf("%.*s %-2d %-4d (%"Int64"d)\n", indent, blanks, i, selector, i64Value); break; case MQITEM_STRING: /***************************************************************/ /* Item is a string. Obtain the string in a buffer, prepare */ /* the string for displaying and display the index, selector, */ /* string and Character Set ID. */ /***************************************************************/ mqInquireString(dataBag, /* Bag handle */ MQSEL_ANY_SELECTOR, /* Allow any selector */ i, /* Index position in the bag */ LENGTH, /* Maximum length of buffer */ stringVal, /* Buffer to receive string */ &stringLength, /* Actual length of string */ &ccsid, /* Coded character set ID */ &compCode, /* Completion code */ &reason); /* Reason Code */ /***************************************************************/ /* The call can return a warning if the string is too long for */ /* the output buffer and has been truncated, so only check */ /* explicitly for call failure. */ /***************************************************************/ if (compCode == MQCC_FAILED) errors++; else { /************************************************************/ /* Remove trailing blanks from the string and terminate with*/ /* a null. First check that the string should not have been */ /* longer than the maximum buffer size allowed. */ /************************************************************/ if (stringLength > LENGTH) trimLength = LENGTH; else trimLength = stringLength; mqTrim(trimLength, stringVal, stringVal, &compCode, &reason); printf("%.*s %-2d %-4d '%s' %d\n", indent, blanks, i, selector, stringVal, ccsid); } break; case MQITEM_BYTE_STRING: /***************************************************************/ /* Item is a byte string. Obtain the byte string in a buffer, */ /* prepare the byte string for displaying and display the */ /* index, selector and string. */ /***************************************************************/ mqInquireByteString(dataBag, /* Bag handle */ MQSEL_ANY_SELECTOR, /* Allow any selector */ i, /* Index position in the bag */ LENGTH, /* Maximum length of buffer */ byteStringVal, /* Buffer to receive string */ &stringLength, /* Actual length of string */ &compCode, /* Completion code */ &reason); /* Reason Code /***************************************************************/ /* The call can return a warning if the string is too long for */ /* the output buffer and has been truncated, so only check */ /* explicitly for call failure. */ /***************************************************************/ if (compCode == MQCC_FAILED) errors++; else { printf("%.*s %-2d %-4d X'", indent, blanks, i, selector); for (i = 0 ; i < stringLength ; i++) printf(" printf("'\n"); } break; case MQITEM_BAG: /***************************************************************/ /* Item is an embedded bag handle, so call the PrintBagContents*/ /* function again to display the contents. */ /***************************************************************/ mqInquireBag(dataBag, /* Bag handle */ MQSEL_ANY_SELECTOR, /* Allow any selector */ i, /* Index position in the bag */ &bagHandle, /* Returned embedded bag hdle*/ &compCode, /* Completion code */ &reason); /* Reason Code */ if (compCode != MQCC_OK) errors++; else { printf("%.*s %-2d %-4d (%d)\n", indent, blanks, i, selector, bagHandle); if (selector == MQHA_BAG_HANDLE) printf(" else printf(" PrintBagContents(bagHandle, indent+INDENT); } break; default: printf(" } } } return errors; }