/***************************************************************************/ /* */ /* (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. */ /* */ /* Each copy of any portion of this sample program or any derivative */ /* work, must include the above copyright notice and disclaimer of */ /* warranty. */ /* */ /***************************************************************************/ /* */ /* Program name: mqsync */ /* */ /* Description: Sample C program that shows WebSphere MQ syncpointing of */ /* messages with an MQPUT */ /* */ /***************************************************************************/ /* */ /* Function: */ /* */ /* This program is a modified version of the AMQSPUT0.C program. It */ /* has been changed to allow for messages to be put in syncpoint by */ /* checking the message buffer for the following text: */ /* */ /* SYNC or sync: the message is to be put in syncpoint */ /* CMIT or cmit: the syncpointed messages are to be committed */ /* BACK or back: the syncpointed messages are to be backed out */ /* */ /* The text must be in all upper case or all lower case and can be found */ /* any where in the message text. */ /* */ /* If both backout and commit are specified, the backout will be done. */ /* The best way to run this program is in conjunction with the amqsget */ /* sample program. The mqsync program can be run in one window while */ /* the amqsget program can be run in another. The mqsync program can */ /* be run as follows: */ /* */ /* mqsync SYSTEM.DEFAULT.LOCAL.QUEUE */ /* message 1 */ /* message 2 SYNC */ /* message 3 */ /* message 4 sync */ /* message 5 cmit */ /* message 6 sync */ /* message 7 */ /* message 8 back */ /* message 9 */ /* */ /* The amqsget program would then run as follows: */ /* */ /* amqsget SYSTEM.DEFAULT.LOCAL.QUEUE */ /* message 1 */ /* message 3 */ /* message 5 cmit shows up here because not in sync */ /* message 2 SYNC */ /* message 4 sync */ /* message 7 */ /* message 8 back this caused message 6 to be disarded */ /* message 9 */ /* */ /* This program has been tested with the MSVC++ 6.0 compiler: */ /* */ /* cl -MT -Z7 -c -W1 -D_X86=1 -DWIN32 mqsync.c */ /* link -OUT:mqsync.exe mqsync.obj mqm.lib */ /* */ /* Note: Use mqic32.Lib instead of mqm.Lib if you want a client connect. */ /* */ /* Note 2: This program does NOT use the MQBEGIN API. This API can be */ /* used when the queue manager is the only participant in the unit */ /* of work. However, it is really designed to be used when */ /* WebSphere MQ is the transaction manager for a global unit of */ /* work. */ /* */ /***************************************************************************/ /* */ /* mqsync has 2 parameters: */ /* queue name (required) */ /* queue manager name (optional) */ /* */ /***************************************************************************/ #include #include #include #include int main(int argc, char **argv) { FILE *fp; /* Declare file and character for sample input */ /* Declare MQI structures needed */ MQOD od = {MQOD_DEFAULT}; /* Object Descriptor */ MQMD md = {MQMD_DEFAULT}; /* Message Descriptor */ MQPMO pmo = {MQPMO_DEFAULT}; /* put message options */ MQHCONN Hcon; /* connection handle */ MQHOBJ Hobj; /* object handle */ MQLONG O_options; /* 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 */ MQLONG BackCode; /* Completion code for MQBACK */ MQLONG CmitCode; /* Completion code for MQCMIT */ MQLONG BackReason; /* reason code for MQBACK */ MQLONG CmitReason; /* reason code for MQCMIT */ int bSyncPoint = 0; /* indicator if messages are in syncpoint */ MQLONG buflen; /* buffer length */ char buffer[100]; /* message buffer */ char QMName[50]; /* queue manager name */ printf("Sample mqsync start\n"); if (argc < 2) { printf("Required parameter missing - queue name\n"); exit(99); } else { printf(" Use SYNC or sync in message text for syncpoint'ed message\n"); printf(" Use CMIT or cmit in message text to commit messages\n"); printf(" Use BACK or back in message text to backout (discard) messages\n"); } /******************************************************************/ /* Connect to queue manager */ /******************************************************************/ QMName[0] = 0; /* default */ if (argc > 2) { strcpy(QMName, argv[2]); } MQCONN(QMName, &Hcon, &CompCode, &CReason); /*******************************************/ /* report reason and stop if it failed */ /*******************************************/ if (CompCode == MQCC_FAILED) { printf("MQCONN ended with reason code %ld\n", CReason); exit( (int)CReason ); } /******************************************************************/ /* Use first parameter as the name of the target queue */ /******************************************************************/ strncpy(od.ObjectName, argv[1], (size_t)MQ_Q_NAME_LENGTH); printf("target queue is %s\n", od.ObjectName); /******************************************************************/ /* Open the target message queue for output */ /******************************************************************/ O_options = MQOO_OUTPUT /* open queue for output */ + MQOO_FAIL_IF_QUIESCING; /* but not if MQM stopping */ MQOPEN(Hcon, &od, O_options, &Hobj, &OpenCode, &Reason); /**********************************************/ /* report reason, if any; stop if failed */ /**********************************************/ if (Reason != MQRC_NONE) { printf("MQOPEN ended with reason code %ld\n", Reason); } if (OpenCode == MQCC_FAILED) { printf("unable to open queue for output\n"); } /****************************************************************/ /* Read lines from the file and put them to the message queue */ /* Loop until null line or end of file, or there is a failure */ /****************************************************************/ CompCode = OpenCode; /* use MQOPEN result for initial test */ fp = stdin; memcpy(md.Format, /* character string format */ MQFMT_STRING, (size_t)MQ_FORMAT_LENGTH); while (CompCode != MQCC_FAILED) { if (fgets(buffer, sizeof(buffer), fp) != NULL) { buflen = strlen(buffer); /* length without null */ if (buffer[buflen-1] == '\n') { /* last char is a new-line */ buffer[buflen-1] = '\0'; /* replace new-line with null */ --buflen; /* reduce buffer length */ } } else { buflen = 0; /* treat EOF same as null line */ } /****************************************************************/ /* If we got a buffer, put it to the message queue. */ /****************************************************************/ if (buflen > 0) { memcpy(md.MsgId, /* reset MsgId to get a new one */ MQMI_NONE, sizeof(md.MsgId) ); memcpy(md.CorrelId, /* reset CorrelId to get a new one */ MQCI_NONE, sizeof(md.CorrelId) ); /***************************************************************/ /* See if the message text contains SYNC or sync. If it does, */ /* turn the MQPMO_SYNCPOINT option on. */ /***************************************************************/ if ( strstr(buffer, "SYNC") || strstr(buffer, "sync")) { pmo.Options = MQPMO_SYNCPOINT; bSyncPoint = 1; } else { pmo.Options = MQPMO_NO_SYNCPOINT; } MQPUT(Hcon, Hobj, &md, &pmo, buflen, buffer, &CompCode, &Reason); /*************************/ /* report reason, if any */ /*************************/ if (Reason != MQRC_NONE) { printf("MQPUT ended with reason code %ld\n", Reason); } /*************************************************************/ /* See if the message text indicates to back out or commit */ /* the syncpointed messages. The message has already been */ /* put on the message queue. */ /*************************************************************/ if ( strstr(buffer, "BACK") || strstr(buffer, "back") ) { bSyncPoint = 0; MQBACK(Hcon, &BackCode, &BackReason); if (BackReason != MQRC_NONE) { printf("MQBACK ended with reason code %ld\n", BackReason); } } else if ( strstr(buffer, "CMIT") || strstr(buffer, "cmit") ) { bSyncPoint = 0; MQCMIT(Hcon, &CmitCode, &CmitReason); if (CmitReason != MQRC_NONE) { printf("MQCMIT ended with reason code %ld\n", CmitReason); } } } else { /* satisfy end condition when empty line is read */ CompCode = MQCC_FAILED; } } /* end while */ /**************************************************************/ /* If the flag that indicates there are messages in syncpoint */ /* is turned on, then commit the messages before exiting. */ /**************************************************************/ if (bSyncPoint) { printf("Syncpoint not done in loop, performing now\n"); MQCMIT(Hcon, &CmitCode, &CmitReason); if (CmitReason != MQRC_NONE) { printf("MQCMIT ended with reason code %ld\n", CmitReason); } } /* endif */ /****************************************************************/ /* Close the target queue (if it was opened) */ /****************************************************************/ if (OpenCode != MQCC_FAILED) { C_options = 0; MQCLOSE(Hcon, &Hobj, C_options, &CompCode, &Reason); /* report reason, if any */ if (Reason != MQRC_NONE) { printf("MQCLOSE ended with reason code %ld\n", Reason); } } /****************************************************************/ /* Disconnect from MQM if not already connected */ /****************************************************************/ if (CReason != MQRC_ALREADY_CONNECTED) { MQDISC(&Hcon, &CompCode, &Reason); /* report reason, if any */ if (Reason != MQRC_NONE) { printf("MQDISC ended with reason code %ld\n", Reason); } } /******************************************************************/ /* End of MQSYNC */ /******************************************************************/ printf("Sample mqsync end\n"); return(0); }