Oops, scenario2.txt was missing the 'get message under cursor' option and scenario3.txt was the wrong code. I have corrected them (see attached).
Regards, Roger Lacroix
At 01:41 AM 8/3/2004, you wrote:
T.Rob,
Excellent. Very well said. I hope Bank of America pays you well. :))
For those that were interested in the GMO settings, I have attached 3 code C snippets that will demonstrate the 3 scenarios that I listed in my previous email.
Just to summarize what I have learned from these 3 test scenarios: - Originally, when I was doing my testing, I thought that the 'Get message under cursor' call moved the Destructive Get cursor. I was wrong. It uses the Browse cursor. Basically, I was wondering if anyone knew of a trick to get it to move (except for specifying a search criteria). But it appears there is none.
- Therefore, if I want to delete messages # 5,6 & 7 (not knowing the MsgId or CorrelId) in a queue with 10 messages, I will have to browse one by one until I get to # 5. Then use Get message under cursor, followed by Browse Next then Get message under cursor, etc...
In a couple of weeks, I will be making an announcement and my questions and test scenarios will become clear. 'Crack' - there's the whip, now back to coding and documentation. Oh god I hate writing documentation!!! :))
Regards, Roger Lacroix
At 04:06 PM 8/2/2004, you wrote:Hi Pavel,
I think I have to address these in context to see below...
> Well, although this is true that there is no direct controls > of the cursor, the documentation is specific enough about the > behavior of the cursor. It calls it "browse cursor" and > explains how exactly the behavior of MQGET with > MQGMO_MSG_UNDER_CURSOR, MQGMO_BROWSE_MSG_UNDER_CURSOR > etc.depends on this cursor's position.
Ok, with you so far...
> What it does not > explain is what happens to the cursor after getting a message > with MQGMO_MSG_UNDER_CURSOR
The manual lists only two ways to move the cursor: "The message pointed to by the browse cursor is the one that was last retrieved using either the MQGMO_BROWSE_FIRST or the MQGMO_BROWSE_NEXT option."
Since the cursor is moved only by a browse, a successful destructive GET points to a non-retrievable message. The manual says that "If the browse cursor is not currently pointing to a retrievable message, an error is returned by the MQGET call."
So after getting a message with MQGMO_MSG_UNDER_CURSOR, the cursor does not move nor does it point to a retrievable message.
> -- and Roger's experiments seem > to show some contradictory behavior -- although he has not > confirmed all the MQGMO options he used in every scenario yet.
When he browsed to a message and then issued non-browse GET calls, the messages were delivered from the head of the queue. When he used MQGMO_BROWSE_NEXT followed by MQGMO_MSG_UNDER_CURSOR he got the target messages. The only contradiction I saw was an expectation that a non-browse GET would honor the browse cursor and that doing a non-browse GET would advance the browse cursor. But the manual contains a paragraph that says "Note that the browse cursor is not moved by nonbrowse MQGET calls using the same Hobj handle." This is why I thought Roger was seeing the correct and expected behavior all along.
> BTW, you mentioned that using priorities may make the cursor > concept 'abstract' but priorities are almost ignored when you > use MQGMO_BROWSE_NEXT; basically, you will never get a higher > priority message until you reset the cursor, say, with > MQGMO_BROWSE_FIRST. This is the documented behavior but I > learned this hard way.. So, I would say, using the cursor may > make priority concept abstract, not other way around :-)
Small clarification here but I mentioned priority along with logical/physical ordering, message grouping, message segmentation and concurrent usage as a few of the factors contributing to the dynamic nature of the browse cursor. The premise was that position (as opposed to message content) is a poor way to select messages for deletion from the queue. If you throw away all the factors *except* priority, it's a completely different illustration.
-- T.Rob
Instructions for managing your mailing list subscription are provided in the Listserv General Users Guide available at http://www.lsoft.com Archive: http://vm.akh-wien.ac.at/MQSeries.archive
gmo.Options = MQGMO_WAIT /* wait for new messages */ + MQGMO_BROWSE_FIRST + MQGMO_CONVERT; /* convert if necessary */ gmo.WaitInterval = 15000; /* 15 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, /* connection handle */ Hobj, /* object handle */ &md, /* message descriptor */ &gmo, /* get message options */ buflen, /* buffer length */ buffer, /* message buffer */ &messlen, /* message length */ &CompCode, /* completion code */ &Reason); /* reason code */ if (CompCode != MQCC_FAILED) { buffer[messlen] = '\0'; /* add terminator */ printf("Browse Next <%s>\n", buffer); i++; if( i == 6 ) { 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; gmo.Options = MQGMO_WAIT /* wait for new messages */ + MQGMO_MSG_UNDER_CURSOR + MQGMO_CONVERT; /* convert if necessary */ MQGET(Hcon, /* connection handle */ Hobj, /* object handle */ &md, /* message descriptor */ &gmo, /* get message options */ buflen, /* buffer length */ buffer, /* message buffer */ &messlen, /* message length */ &CompCode, /* completion code */ &Reason); /* reason code */ if (CompCode != MQCC_FAILED) { buffer[messlen] = '\0'; /* add terminator */ printf("Destructive 'Get message under cursor' <%s>\n", buffer); } else printf("Error reason code=%d\n", Reason); } if( i > 6 ) { 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; gmo.Options = MQGMO_WAIT /* wait for new messages */ + MQGMO_CONVERT; /* convert if necessary */ MQGET(Hcon, /* connection handle */ Hobj, /* object handle */ &md, /* message descriptor */ &gmo, /* get message options */ buflen, /* buffer length */ buffer, /* message buffer */ &messlen, /* message length */ &CompCode, /* completion code */ &Reason); /* reason code */ if (CompCode != MQCC_FAILED) { buffer[messlen] = '\0'; /* add terminator */ printf("Destructive Get <%s>\n", buffer); } else printf("Error reason code=%d\n", Reason); } } else printf("Error reason code=%d\n", Reason); gmo.Options = MQGMO_WAIT /* wait for new messages */ + MQGMO_BROWSE_NEXT + MQGMO_CONVERT; /* convert if necessary */ }
gmo.Options = MQGMO_WAIT /* wait for new messages */ + MQGMO_BROWSE_FIRST + MQGMO_CONVERT; /* convert if necessary */ gmo.WaitInterval = 15000; /* 15 second limit for waiting */ browsing = 1; 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, /* connection handle */ Hobj, /* object handle */ &md, /* message descriptor */ &gmo, /* get message options */ buflen, /* buffer length */ buffer, /* message buffer */ &messlen, /* message length */ &CompCode, /* completion code */ &Reason); /* reason code */ if (CompCode != MQCC_FAILED) { buffer[messlen] = '\0'; /* add terminator */ if( browsing == 1 ) printf("Browse Next <%s>\n", buffer); else printf("Destructive Get <%s>\n", buffer); i++; if( (i == 6) && (browsing == 1) ) { 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; gmo.Options = MQGMO_WAIT /* wait for new messages */ + MQGMO_MSG_UNDER_CURSOR + MQGMO_CONVERT; /* convert if necessary */ MQGET(Hcon, /* connection handle */ Hobj, /* object handle */ &md, /* message descriptor */ &gmo, /* get message options */ buflen, /* buffer length */ buffer, /* message buffer */ &messlen, /* message length */ &CompCode, /* completion code */ &Reason); /* reason code */ if (CompCode != MQCC_FAILED) { buffer[messlen] = '\0'; /* add terminator */ printf("Destructive 'Get message under cursor' <%s>\n", buffer); } else printf("Error reason code=%d\n", Reason); browsing = 0; } } else printf("Error reason code=%d\n", Reason); if ( i < 6 ) gmo.Options = MQGMO_WAIT + MQGMO_BROWSE_NEXT + MQGMO_CONVERT; else gmo.Options = MQGMO_WAIT + MQGMO_CONVERT; }