ASG
IBM
Zystems
Cressida
Icon
Netflexity
 
  MQSeries.net
Search  Search       Tech Exchange      Education      Certifications      Library      Info Center      SupportPacs      LinkedIn  Search  Search                                                                   FAQ  FAQ   Usergroups  Usergroups
 
Register  ::  Log in Log in to check your private messages
 
RSS Feed - WebSphere MQ Support RSS Feed - Message Broker Support

MQSeries.net Forum Index » IBM MQ API Support » Batch calling MQPUT1 and MQGET errors with MQRC 2018

Post new topic  Reply to topic
 Batch calling MQPUT1 and MQGET errors with MQRC 2018 « View previous topic :: View next topic » 
Author Message
hivetri
PostPosted: Wed Jan 31, 2018 6:22 am    Post subject: Batch calling MQPUT1 and MQGET errors with MQRC 2018 Reply with quote

Newbie

Joined: 31 Jan 2018
Posts: 4

MQServer:

Queue Manager and Queues defined in MQServer 6 running on AIX 5.3

MQClient:

MQ v8 client installed on AIX 7.1

Caller program is a "batch application" written in OpenROAD 6.
It calls a wrapper library (shared object) written in C for AIX.

a. Batch application repeatedly calls the wrapper procedure inside a FOR loop to pump messages into the queue.
b. wrapper procedure calls MQCONN, MQPUT1 and MDISC in that order.
c. MQPUT1 returns 2018 error code.
d. Same with MQGET api which also returns 2018 error code
e. It fails in the 1st iteration itself.
f. This is a code currently working in production which is getting remediated to supported platform.

Request your help to resolve this issue.

Code:

int      mqizsend_3gl(PMQCHAR AppName, PMQCHAR QMName, PMQCHAR QName, PMQCHAR RQMName, PMQCHAR RQName, PMQCHAR sourceName, uLong sourceLen, int zLevel, char *MsgID, MQLONG *CompCode, MQLONG *CReason)
{
    /* Initialise Objects and Variables */
    int      i;
    int     ch;
    int     zresult;
   char   ZipName[MAX_PATH];
    uLong   bufferLimit;
    Bytef   *source;
    MQHCONN   Hcon;
    MQHOBJ   HObj;
    MQLONG   Options;
    MQLONG   DCompCode;
    MQLONG   DCReason;
    MQOD     od      = {MQOD_DEFAULT};
    MQMD     md      = {MQMD_DEFAULT};
    MQPMO    pmo   = {MQPMO_DEFAULT};
    FILE     *fp;

    if (zLevel == 0)
   {
        memcpy(md.Format, MQFMT_STRING, (size_t)MQ_FORMAT_LENGTH);
        bufferLimit = sourceLen;
   }
   else
   {
      strcpy(ZipName, sourceName);
      strcat(ZipName,".zip");
      makezip_3gl(ZipName, sourceName, 0);
      strcat(sourceName,".zip");
        bufferLimit = compressBound(sourceLen);
      sourceLen = bufferLimit + 1;
        memcpy(md.Format, MQFMT_NONE, (size_t)MQ_FORMAT_LENGTH);
   }

   /* Allocate Source buffer */
   source = malloc( (size_t) sourceLen + 1);
    if(source == NULL)
   {
        return( (int) -10 );
    }
    if((fp = fopen(sourceName,"r+")) == NULL)
   {
        free(source);
        return( (int) -11 );
    }
   /* Read in characters and place them in "source": */
   ch = fgetc( fp );
   for( i=0; (i < sourceLen ) && ( feof( fp ) == 0 ); i++ )
   {
      source[i] = (char)ch;
      ch = fgetc( fp );
   }

   /* Add null to end string */
   source[i] = '\0';
   fclose( fp );

    /* Connect to Queue Manager */
    MQCONN(QMName, &Hcon, CompCode, CReason);

    if (*CompCode == MQCC_FAILED)
    {
        free(source);
        return( (int)*CReason );
    }

    /* Open Message Queue for output*/
    strcpy(od.ObjectName,QName);

    /* Put uncpmressed/compressed stream onto Queue */
   strcpy(md.ReplyToQ,RQName);
   strcat(md.ReplyToQ,"?targetClient=1");
   strcpy(md.ReplyToQMgr,RQMName);
   strcpy(md.PutApplName,AppName);
   md.MsgType         = MQMT_REQUEST;
   md.Priority         = 4;

    MQPUT1( Hcon, &od, &md, &pmo, (MQLONG)bufferLimit, (PMQVOID)source, CompCode, CReason);
    MQDISC( &Hcon, &DCompCode, &DCReason);
    if (*CompCode == MQCC_FAILED)
    {
        free(source);
        return( (int)*CReason );
    }
    else
    {
        for (i = 0 ; i < MQ_MSG_ID_LENGTH ; i++)
            sprintf(MsgID + 2*i,"%02x",md.MsgId[i] );
        free(source);
        return MQCC_OK;
    }

}


Code:

int      mqizrecv_3gl(PMQCHAR QMName, PMQCHAR QName, char * dest, MQLONG tWait, MQLONG *CompCode, MQLONG *CReason, MQLONG compressFlag)
{
    /* Initialise Objects and Variables */
    int      zresult;
   int     presult;
   int     i;
    uLong   bufferLimit;
    char   *source;
    MQHCONN   Hcon;
    MQHOBJ   HObj;
    MQLONG   Options;
    MQLONG   COptions;
    MQLONG   DCompCode;
    MQLONG   DCReason;
    MQLONG   RCompCode;
    MQLONG   RCReason;
    MQLONG   CCompCode;
    MQLONG   CCReason;
    MQLONG   messageLen;
   MQRFH2   *rfh_mess;
    MQOD    od          = {MQOD_DEFAULT};
    MQMD    md          = {MQMD_DEFAULT};
    MQGMO   gmo           = {MQGMO_DEFAULT};

   /* Allocate buffer */
   source = malloc( (size_t) 1024001 );
    if(source == NULL)
   {
        return( (int) -10 );
    }

    /* Connect to Queue Manager */
    MQCONN(QMName, &Hcon, CompCode, CReason);

    if (*CompCode == MQCC_FAILED)
    {
      free(source);
        return( (int)*CReason );
    }

    /* Open Message Queue for output*/
    strcpy(od.ObjectName,QName);
    Options = MQOO_INPUT_AS_Q_DEF | MQOO_FAIL_IF_QUIESCING;

    MQOPEN( Hcon, &od, Options, &HObj, CompCode, CReason);
    if (*CompCode == MQCC_FAILED)
    {
        MQDISC( &Hcon, &DCompCode, &DCReason);
      free(source);
        return( (int)*CReason );
    }

    /* Get compressed stream from Queue */
/*    memcpy(md.Format, MQFMT_RF_HEADER_2, (size_t)MQ_FORMAT_LENGTH); */
    bufferLimit = 1024000;
/*    md.Encoding       = 273;
    md.CodedCharSetId = 819; */
    /* get message options */
    gmo.Version = MQGMO_VERSION_2;
    gmo.MatchOptions = MQMO_NONE;
    gmo.Options = MQGMO_WAIT + MQGMO_CONVERT;
    gmo.WaitInterval = tWait;
    /* close options */
    COptions = MQCO_NONE;

    MQGET( Hcon, HObj, &md, &gmo, bufferLimit, source, &messageLen, CompCode, CReason);
    if (*CompCode == MQCC_FAILED)
    {
        MQCLOSE( Hcon, &HObj, COptions, &CCompCode, &CCReason);
        MQDISC( &Hcon, &DCompCode, &DCReason);
      free(source);
        return( (int)*CReason );
    }

    MQCLOSE( Hcon, &HObj, COptions, &CCompCode, &CCReason);
    MQDISC( &Hcon, &DCompCode, &DCReason);

   compressFlag = 0;
   if (memcmp(md.Format, MQFMT_RF_HEADER_2, sizeof(MQFMT_RF_HEADER_2)) == 0)
   {
      rfh_mess = (MQRFH2*) source;
        dest = source + MQRFH_STRUC_LENGTH_FIXED_2;
      /* presult = parse_reply(dest, &RCompCode, &RCReason, msgtext); */
      /* dest = msgtext; */
   }
   else if (compressFlag == 0)
   {
      if (messageLen > 256)
      {
         strncpy(dest,source,225);
         strcat(dest,"</MESSAGE>\n</JETFORM-RESPONSE>");
      }
      else
      {
         strncpy(dest,source, messageLen);
         dest[messageLen + 1] = '\0';

      }
   }
    else
    {
      /* Allocate Memory Buffer */
      if (bufferLimit * 2 > messageLen * 100)
      {
         bufferLimit = bufferLimit * 2;
      } else {
         bufferLimit = messageLen * 100;
      }

      /* Uncompress Data Stream */
      zresult = uncompress(dest, &bufferLimit, source, messageLen);   
      if (zresult != 0)
      {
         free(source);
         return zresult;
      }
   }
   free(source);
    return MQCC_OK;
}
Back to top
View user's profile Send private message
Vitor
PostPosted: Wed Jan 31, 2018 7:05 am    Post subject: Re: Batch calling MQPUT1 and MQGET errors with MQRC 2018 Reply with quote

Grand High Poobah

Joined: 11 Nov 2005
Posts: 26093
Location: Texas, USA

hivetri wrote:
b. wrapper procedure calls MQCONN, MQPUT1 and MDISC in that order.


This is a horribly inefficient programming model. The connect and disconnect operations are very resource expensive and best practice (especially in a high volume batch operation) is to connect, open, put repeatedly, close and disconnect.

hivetri wrote:
c. MQPUT1 returns 2018 error code.
d. Same with MQGET api which also returns 2018 error code
e. It fails in the 1st iteration itself.
f. This is a code currently working in production which is getting remediated to supported platform.


I would theorize that all this runs in a single thread on the old platform, but on the new platform the work is being split out across multiple threads so the connection handle isn't in scope for the api.
_________________
Honesty is the best policy.
Insanity is the best defence.
Back to top
View user's profile Send private message
hivetri
PostPosted: Wed Jan 31, 2018 1:57 pm    Post subject: Re: Batch calling MQPUT1 and MQGET errors with MQRC 2018 Reply with quote

Newbie

Joined: 31 Jan 2018
Posts: 4

Hi,

I forgot to add the following.

Previously, batch application ran in the same AIX 5.3 server and connected to the local QMgr.

Remediated implementation moved the batch application to another AIX 7.1 server and makes a client connection using Channel Tab.

Application architecture maintained the same way as single threaded.


Vitor wrote:
hivetri wrote:
b. wrapper procedure calls MQCONN, MQPUT1 and MDISC in that order.


This is a horribly inefficient programming model. The connect and disconnect operations are very resource expensive and best practice (especially in a high volume batch operation) is to connect, open, put repeatedly, close and disconnect.

hivetri wrote:
c. MQPUT1 returns 2018 error code.
d. Same with MQGET api which also returns 2018 error code
e. It fails in the 1st iteration itself.
f. This is a code currently working in production which is getting remediated to supported platform.


I would theorize that all this runs in a single thread on the old platform, but on the new platform the work is being split out across multiple threads so the connection handle isn't in scope for the api.
Back to top
View user's profile Send private message
gbaddeley
PostPosted: Wed Jan 31, 2018 3:44 pm    Post subject: Reply with quote

Jedi

Joined: 25 Mar 2003
Posts: 2492
Location: Melbourne, Australia

Also horribly inefficient:
Code:
/* Read in characters and place them in "source": */
   ch = fgetc( fp );
   for( i=0; (i < sourceLen ) && ( feof( fp ) == 0 ); i++ )
   {
      source[i] = (char)ch;
      ch = fgetc( fp );
   }

The code should make one call to fread() to read all characters into the source array at once. Eg.
Code:
fread( fp, sourceLen, 1, pFile );

Also, MQ messages do not need to be null terminated.
_________________
Glenn
Back to top
View user's profile Send private message
hivetri
PostPosted: Wed Jan 31, 2018 7:22 pm    Post subject: Reply with quote

Newbie

Joined: 31 Jan 2018
Posts: 4

Hmm... parking the string management suggestions for the time being.

We tried to PUT to a different queue (under the same QMgr) and still returns 2018 error code.

Additionally, the wrapper also has separate methods for MQCONN, MQOPEN, MQGET, MQPUT1, MQDISC apis.

Would it be good idea to move the MQ calls to the parent (caller) application and instantiate the MQCONN once outside the for loop and reuse the handle inside the loop?
Back to top
View user's profile Send private message
Vitor
PostPosted: Thu Feb 01, 2018 5:53 am    Post subject: Reply with quote

Grand High Poobah

Joined: 11 Nov 2005
Posts: 26093
Location: Texas, USA

hivetri wrote:
Would it be good idea to move the MQ calls to the parent (caller) application and instantiate the MQCONN once outside the for loop and reuse the handle inside the loop?


Heck yes - see my comments above regarding the expense of the connect.

A local bindings connection is an RPC call to the queue manager, which I bet is expressed differently inside the AIX thread / storage model than a TCP/IP session. So I bet you fluked not getting a 2018 with this horrible code in the old system because you were bolted to the queue manager, and it would be an interesting experiment to see if this still works on the new set up if it's a bindings rather than a client connection.
_________________
Honesty is the best policy.
Insanity is the best defence.
Back to top
View user's profile Send private message
fjb_saper
PostPosted: Thu Feb 01, 2018 6:45 am    Post subject: Reply with quote

Grand High Poobah

Joined: 18 Nov 2003
Posts: 20696
Location: LI,NY


And please add an MQCLOSE to that wrapper...
_________________
MQ & Broker admin
Back to top
View user's profile Send private message Send e-mail
Vitor
PostPosted: Thu Feb 01, 2018 7:06 am    Post subject: Reply with quote

Grand High Poobah

Joined: 11 Nov 2005
Posts: 26093
Location: Texas, USA

fjb_saper wrote:

And please add an MQCLOSE to that wrapper...


!!!!


Good catch!
_________________
Honesty is the best policy.
Insanity is the best defence.
Back to top
View user's profile Send private message
RogerLacroix
PostPosted: Thu Feb 01, 2018 1:28 pm    Post subject: Reply with quote

Jedi Knight

Joined: 15 May 2001
Posts: 3252
Location: London, ON Canada

Are you using the same makefile on AIX to build the application? Did you update the link statement in makefile to use the MQ client library rather than MQ bindings library?

i.e. "-lmqic" vs "-lmqm"

https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.5.0/com.ibm.mq.dev.doc/q028350_.htm

Regards,
Roger Lacroix
Capitalware Inc.
_________________
Capitalware: Transforming tomorrow into today.
Connected to MQ!
Twitter
Back to top
View user's profile Send private message Visit poster's website
hivetri
PostPosted: Tue Feb 06, 2018 5:11 am    Post subject: Reply with quote

Newbie

Joined: 31 Jan 2018
Posts: 4

RogerLacroix wrote:
Are you using the same makefile on AIX to build the application? Did you update the link statement in makefile to use the MQ client library rather than MQ bindings library?

i.e. "-lmqic" vs "-lmqm"

https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.5.0/com.ibm.mq.dev.doc/q028350_.htm

Regards,
Roger Lacroix
Capitalware Inc.


Hi,

We did try linking lmqic as well. Still it returns 2018.

What caught my attention in the link is this line in the foot note.

If you are writing an installable service (see the Administering for further information), you need to link to the libmqmzf.a library in a non-threaded application and to the libmqmzf_r.a library in a threaded application.


Our application indeed setup as an AIX service.

Let me try this first thing tomorrow morning.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic  Reply to topic Page 1 of 1

MQSeries.net Forum Index » IBM MQ API Support » Batch calling MQPUT1 and MQGET errors with MQRC 2018
Jump to:  



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
Protected by Anti-Spam ACP
 
 


Theme by Dustin Baccetti
Powered by phpBB © 2001, 2002 phpBB Group

Copyright © MQSeries.net. All rights reserved.