/*****************************************************************************/ /* */ /* (c) Copyright IBM Corp. 2006 All rights reserved. */ /* */ /* This sample program is owned by International Business Machines */ /* Corporation or one of its subsidiaries ("IBM") and is copyrighted */ /* and licensed, not sold. */ /* */ /* You may copy, modify, and distribute this sample program in any */ /* form without payment to IBM, for any purpose including developing, */ /* using, marketing or distributing programs that include or are */ /* derivative works of the sample program. */ /* */ /* The sample program is provided to you on an "AS IS" basis, without */ /* warranty of any kind. IBM HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES, */ /* EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* Some jurisdictions do not allow for the exclusion or limitation of */ /* implied warranties, so the above limitations or exclusions may not */ /* apply to you. IBM shall not be liable for any damages you suffer as */ /* a result of using, modifying or distributing the sample program or */ /* its derivatives. */ /* */ /*****************************************************************************/ /* */ /* Program name: backout */ /* */ /* Description: Sample c program that shows moving a poisoned message to the */ /* backout queue. */ /* */ /*****************************************************************************/ /* */ /* Function: */ /* */ /* This program will get a single message off of a queue enough times */ /* to exceed the backout threshold on the queue. It will then move the */ /* message to the backout queue specified for the queue. */ /* */ /* This program is run as follows: */ /* */ /* backout QUEUE.NAME QMGR */ /* */ /* where */ /* QUEUE.NAME: the name of the queue with the poison message (required) */ /* QMGR : the name of the queue manager (optional); if left off, */ /* the default queue manager will be used. */ /* */ /* In order to run this program, a queue will need to be defined that has a */ /* a backout queue and backout threshold specified. In addition, an actual */ /* queue will need to be defined for the backout queue. This can be done */ /* using runmqsc with the following commands: */ /* */ /* define ql(ORIG.Q) boqname(ORIG.Q.BACKOUT) bothresh(5) */ /* define ql(ORIG.Q.BACKOUT) */ /* */ /* A message can then put put on the ORIG.Q. This backout program will then */ /* read the message 6 times and move it to ORIG.Q.BACKOUT. */ /* */ /* This program has been tested with Microsoft Visual C++ 6.0 and */ /* WebSphere MQ v6.0.1.0 and was built using the following command: */ /* */ /* cl -I\WMQ\tools\c\include backout.c \WMQ\tools\lib\mqm.Lib */ /* */ /*****************************************************************************/ /* */ /* Note: This program is based on the amqsget0.c WebSphere MQ sample. */ /* */ /*****************************************************************************/ #include #include #include #include int main(int argc, char **argv) { /* Declare MQI structures needed */ MQOD odGet = {MQOD_DEFAULT}; /* Object Descriptor */ MQOD odPut = {MQOD_DEFAULT}; /* Object Descriptor */ MQMD md = {MQMD_DEFAULT}; /* Message Descriptor */ MQGMO gmo = {MQGMO_DEFAULT}; /* get message options */ MQPMO pmo = {MQPMO_DEFAULT}; /* get message options */ /** note, sample uses defaults where it can **/ MQHCONN Hcon; /* connection handle */ MQHOBJ HobjGet; /* object handle */ MQHOBJ HobjPut; /* object handle */ MQLONG O_optionsGet; /* MQOPEN options */ MQLONG O_optionsPut; /* MQOPEN options */ MQLONG C_options; /* MQCLOSE options */ MQLONG CompCode; /* completion code */ MQLONG OpenCode; /* MQOPEN completion code */ MQLONG Reason; /* reason code */ MQLONG CReason; /* reason code for MQCONN */ MQBYTE buffer[1001]; /* message buffer */ MQLONG buflen; /* buffer length */ MQLONG messlen; /* message length received */ char QMName[50]; /* queue manager name */ MQLONG inqBO = 1; /* Flag to indicate inquire worked */ MQLONG Select[2]; /* Two selectors: */ MQLONG BoThresh; /* Backout Threshold (integer) */ MQCHAR BoQname[MQ_Q_NAME_LENGTH]; /* Backout Queue Name (char) */ printf("Sample backout start\n"); if (argc < 2) { printf("Required parameter missing - queue name\n"); exit(99); } /******************************************************************/ /* Read the input parameters.... */ /******************************************************************/ strcpy(odGet.ObjectName, argv[1]); QMName[0] = 0; /* default */ if (argc > 2) { strcpy(QMName, argv[2]); } /****************************************************************/ /* Connect to queue manager */ /****************************************************************/ MQCONN(QMName, &Hcon, &CompCode, &CReason); if (CompCode == MQCC_FAILED) { printf("MQCONN failed with CompCode %ld, ReasonCode %ld\n", CompCode, CReason); exit( (int)CReason ); } /******************************************************************/ /* Open the queue for input, inquire (to read backout info), and */ /* save context (so that context can be passed to backout queue). */ /******************************************************************/ O_optionsGet = MQOO_INPUT_AS_Q_DEF /* open queue for input */ + MQOO_SAVE_ALL_CONTEXT + MQOO_INQUIRE + MQOO_FAIL_IF_QUIESCING; /* but not if MQM stopping */ MQOPEN(Hcon, &odGet, O_optionsGet, &HobjGet, &OpenCode, &Reason); if (OpenCode != MQCC_OK) { printf("MQOPEN failed with CompCode %ld, ReasonCode %ld\n", OpenCode, Reason); } else { /***********************************************/ /* We need to build an array of two selectors: */ /* Backout Threshold - an integer */ /* Backout Queue Name - character string */ /* Both are parameters of the queue object. */ /***********************************************/ Select[0] = MQIA_BACKOUT_THRESHOLD; Select[1] = MQCA_BACKOUT_REQ_Q_NAME; MQINQ(Hcon, HobjGet, 2L, Select, 1L, &BoThresh, MQ_Q_NAME_LENGTH, BoQname, &OpenCode, &Reason); if (CompCode == MQCC_OK) { printf("BackOut Threshold = %ld\n", BoThresh); printf("Backout Requeue Q = %.*s\n", MQ_Q_NAME_LENGTH, BoQname); } else { /******************************************************/ /* If we couldn't get the parameters, show an error. */ /******************************************************/ printf("MQINQ failed with CompCode %ld, ReasonCode %ld\n", OpenCode, Reason); } } /******************************************************************/ /* This loop will get one message from the queue and back it out */ /* until the backout threshold is reached. Once the threshold is */ /* reached, the message will be moved to the backout queue. */ /******************************************************************/ CompCode = OpenCode; /* use MQOPEN or MQINQ for initial test */ gmo.Options = MQGMO_WAIT /* wait for new messages */ + MQGMO_SYNCPOINT /* get messages in syncpoint */ + MQGMO_CONVERT; /* convert if necessary */ gmo.WaitInterval = 5000; /* 5 second limit for waiting */ while (CompCode != MQCC_FAILED) { buflen = sizeof(buffer) - 1; /* buffer size available for GET */ memcpy(md.MsgId, MQMI_NONE, sizeof(md.MsgId)); memcpy(md.CorrelId, MQCI_NONE, sizeof(md.CorrelId)); md.Encoding = MQENC_NATIVE; md.CodedCharSetId = MQCCSI_Q_MGR; MQGET(Hcon, HobjGet, &md, &gmo, buflen, buffer, &messlen, &CompCode, &Reason); /* report reason, if any */ if (Reason != MQRC_NONE) { if (Reason == MQRC_NO_MSG_AVAILABLE) { printf("no more messages\n"); } else { printf("MQGET failed with CompCode %ld, ReasonCode %ld\n", CompCode, Reason); if (Reason == MQRC_TRUNCATED_MSG_FAILED) { CompCode = MQCC_FAILED; } } } /****************************************************************/ /* If we got the message, check to see if the backout count */ /* exceeds the threshold. If it does, we'll move the message */ /* to the backout queue. */ /****************************************************************/ if (CompCode != MQCC_FAILED) { if (md.BackoutCount <= BoThresh) { printf(" BackoutCount: %ld of %ld\n", md.BackoutCount, BoThresh); MQBACK(Hcon, &CompCode, &Reason); if (CompCode != MQCC_OK) { printf("MQBACK failed with compcode %ld, reason code %ld\n", CompCode, Reason); } } else { printf("Message is poison, moving to %.*s\n", MQ_Q_NAME_LENGTH, BoQname); strncpy(odPut.ObjectName, BoQname, MQ_Q_NAME_LENGTH); O_optionsPut = MQOO_OUTPUT + MQOO_FAIL_IF_QUIESCING + MQOO_PASS_ALL_CONTEXT; MQOPEN(Hcon, &odPut, O_optionsPut, &HobjPut, &CompCode, &Reason); if (CompCode != MQCC_OK) { printf("MQOPEN of backout queue failed with CompCode %ld, ReasonCode %ld\n", CompCode, Reason); } else { pmo.Options = pmo.Options + MQPMO_PASS_ALL_CONTEXT + MQPMO_SYNCPOINT; pmo.Context = HobjGet; /* handle of input queue */ MQPUT(Hcon, HobjPut, &md, &pmo, messlen, buffer, &CompCode, &Reason); if (CompCode != MQCC_OK) { printf("MQPUT of backout queue failed with CompCode %ld, ReasonCode %ld\n", CompCode, Reason); } C_options = 0; /* no close options */ MQCLOSE(Hcon, &HobjPut, C_options, &CompCode, &Reason); if (CompCode != MQCC_OK) { printf("MQCLOSE of backout queue failed with CompCode %ld, ReasonCode %ld\n", CompCode, Reason); } } MQCMIT(Hcon, &CompCode, &Reason); if (CompCode != MQCC_OK) { printf("MQCLOSE of backout queue failed with CompCode %ld, ReasonCode %ld\n", CompCode, Reason); } /**************************************************/ /* At this point, we've moved the poison message. */ /* We'll set our loop CompCode so that the loop */ /* exits. */ /**************************************************/ CompCode = MQCC_FAILED; } } } /****************************************************************/ /* Close the source queue (if it was opened) */ /****************************************************************/ if (OpenCode != MQCC_FAILED) { C_options = 0; /* no close options */ MQCLOSE(Hcon, &HobjGet, C_options, &CompCode, &Reason); if (Reason != MQRC_NONE) { printf("MQCLOSE of source queue failed with CompCode %ld, ReasonCode %ld\n", CompCode, Reason); } } /****************************************************************/ /* Disconnect from MQM if not already connected */ /****************************************************************/ if (CReason != MQRC_ALREADY_CONNECTED ) { MQDISC(&Hcon, &CompCode, &Reason); if (Reason != MQRC_NONE) { printf("MQDISC failed with CompCode %ld, ReasonCode %ld\n", CompCode, Reason); } } printf("Sample backout end\n"); return(0); }