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;
}

Reply via email to