|
RSS Feed - WebSphere MQ Support
|
RSS Feed - Message Broker Support
|
Message under cursor |
« View previous topic :: View next topic » |
Author |
Message
|
markt |
Posted: Sun Aug 01, 2004 5:41 am Post subject: |
|
|
 Knight
Joined: 14 May 2002 Posts: 508
|
There is no "destructive get" cursor as such. You can either get the message that is under the browse cursor, or you can get the first message on the queue that meets your retrieval criteria. Which seems to be the behaviour all your tests are reporting.
(Hence the name of the GMO option - it refers to CURSOR, not BROWSE_CURSOR.)
The only way of getting a specific message that is guaranteed to be unique (even with msgid/correlid) is to use MsgToken, but that is not available in all V5.3 environments. |
|
Back to top |
|
 |
PeterPotkay |
Posted: Sun Aug 01, 2004 6:03 am Post subject: |
|
|
 Poobah
Joined: 15 May 2001 Posts: 7722
|
Quote: |
The only way of getting a specific message that is guaranteed to be unique (even with msgid/correlid) is to use MsgToken, but that is not available in all V5.3 environments.
|
What is MsgToken? Are you referring to the Accounting Token? If yes, since an application can set it just like it can set the MsgID and CorrelID, we still have the same problem.
An app can theoritically dump thousands of messages to the queue, all with the exact same MQMD, but different message buffers. Not that they should, but they can. Either the tool needs to warn the user that they may not get the message they intend if the MQMD is not unique, or the tool must use a different method of matching the message selected in the GUI with the actually message on the queue, like an internal index, which itself is vulnerable to message expiring and/or being gotten/put to the queue since the index was built.
The easiest solution of course is if the apps just generate unique IDs, but there is no way to insure that will always happen. _________________ Peter Potkay
Keep Calm and MQ On |
|
Back to top |
|
 |
markt |
Posted: Sun Aug 01, 2004 6:07 am Post subject: |
|
|
 Knight
Joined: 14 May 2002 Posts: 508
|
MsgToken - it's in the books. |
|
Back to top |
|
 |
jefflowrey |
Posted: Sun Aug 01, 2004 6:46 am Post subject: |
|
|
Grand Poobah
Joined: 16 Oct 2002 Posts: 19981
|
markt wrote: |
MsgToken - it's in the books. |
Application Programming Guide,Fourth edition (March 2003) wrote: |
MsgToken
Only supported in WebSphere MQ for z/OS.
MsgToken uniquely identifies a message.
|
I think it's the "Only supported in WebSphere MQ for z/OS" that causes most of us to ignore this parameter. _________________ I am *not* the model of the modern major general. |
|
Back to top |
|
 |
RogerLacroix |
Posted: Sun Aug 01, 2004 7:56 am Post subject: |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
Hi Gunter,
I fully agree with you. You have described 'Browse Get' and 'Destructive Get under Cursor'. That is my Scenario #2.
'Destructive Get under Cursor' uses the Browse Cursor to get the message.
There are 2 cursors: Browse Cursor and Destructive Get Cursor. So to summarize:
- Browse Cursor is used by 'Browse Get' and 'Destructive Get under Cursor'.
- Destructive Get Cursor is used only by 'Destructive Get' only.
Don't believe me, try your own code. I deleted 1 line (MQGMO_MSG_UNDER_CURSOR ) and added error messages. Put 10 messages in queue like "This is message ##" then run the code.
I wish I could get a picture of your face when you see the results.
Code: |
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 > 5 && i < 9 )
{
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);
printf("Destructive Get <%s>\n", buffer);
}
}
else
printf("Error reason code=%d\n", Reason);
gmo.Options = MQGMO_WAIT /* wait for new messages */
+ MQGMO_BROWSE_NEXT
+ MQGMO_CONVERT; /* convert if necessary */
} |
Regards,
Roger Lacroix _________________ Capitalware: Transforming tomorrow into today.
Connected to MQ!
Twitter
Last edited by RogerLacroix on Sun Aug 01, 2004 8:40 am; edited 1 time in total |
|
Back to top |
|
 |
RogerLacroix |
Posted: Sun Aug 01, 2004 8:09 am Post subject: |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
markt,
Quote: |
There is no "destructive get" cursor as such. |
Sorry, you are wrong.
Quote: |
you can get the first message on the queue that meets your retrieval criteria |
You are referring to Destructive Get cursor. If you don't do a 'Get by MsgID' (or CorrelID or GroupID) then the cursor will be at the first message and the get will retrieve it.
If you do a 'Get by MsgID' (or CorrelID or GroupID) then the Destructive Get cursor will be positioned to the first message that matches the search criteria and the get will retrieve it.
The only thing that has become apparent from all my testing is that an application cannot move either the Browse Cursor or Destructive Get unless you do a get with a search criteria. Although, the 'Get Msg under cursor' gives an interesting illusion.
Regards,
Roger Lacroix _________________ Capitalware: Transforming tomorrow into today.
Connected to MQ!
Twitter |
|
Back to top |
|
 |
markt |
Posted: Sun Aug 01, 2004 10:23 am Post subject: |
|
|
 Knight
Joined: 14 May 2002 Posts: 508
|
>> There is no "destructive get" cursor as such.
>Sorry, you are wrong.
No, I am right. There is nothing in the code that can be considered a "destructive cursor" that moves in the same way as the browse cursor. The queue manager simply retrieves the top criteria-meeting message from the queue when you do a destructive get. If you want to call that search-and-return a cursor, feel free. But it's not what I'd call a cursor; it does not stick anywhere after the retrieval. Your next MQGET will go back to the top and search again.
>> you can get the first message on the queue that meets your retrieval criteria
> You are referring to Destructive Get cursor. If you don't do a 'Get by MsgID' (or CorrelID or GroupID) then the cursor will be at the first message and the get will retrieve it.
I am referring to the fact that when you do a get without specifying MSG_UNDER_CURSOR you will get the first message on the queue that meets your criteria. Which might be the very first message if your criteria do not include specific msgid or correlid or it might be further down if you do specify some of those options. |
|
Back to top |
|
 |
gunter |
Posted: Sun Aug 01, 2004 12:29 pm Post subject: |
|
|
Partisan
Joined: 21 Jan 2004 Posts: 307 Location: Germany, Frankfurt
|
Sorry, I misunderstand the problem.
I think, you can't move a curser through the messages, there is no free access, MQ isn't a database.
You always get the first or the first selected message if msgId or correlationId is set. Even if you use msgId or correlationId, the queue will be searched beginning by the first message, maybe they optimized the code to improve the perforemance.
If you browse a queue, it starts always at the first message and you are be able to get the last message read with MQGMO_MSG_UNDER_CURSOR. You can also implement this feature by GET with the msgId, but I would expect, that MQGMO_MSG_UNDER_CURSOR is faster. _________________ Gunter Jeschawitz
IBM Certified System Administrator - Websphere MQ, 5.3 |
|
Back to top |
|
 |
RogerLacroix |
Posted: Sun Aug 01, 2004 9:25 pm Post subject: |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
markt,
You describe the Destructive Get cursor but you don't want to say it is a 'Destructive Get Cursor'. If you want to call it a green monster from Cincinnati that is fine.
It does move beyond the first position if you did not specify search criteria. It skips over retrieved messages (but not deleted) that are under a current unit of work (global or local) and it skips over messages that are in an unresolved transaction state.
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 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...
Oh yes, I also preach the 'MQ is not a database' mantra but less we forget that MQ internals are from DB2, hence the reason I was looking for a trick.
Regards,
Roger Lacroix _________________ Capitalware: Transforming tomorrow into today.
Connected to MQ!
Twitter |
|
Back to top |
|
 |
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|
|
|