|
RSS Feed - WebSphere MQ Support
|
RSS Feed - Message Broker Support
|
 |
|
Batch calling MQPUT1 and MQGET errors with MQRC 2018 |
« View previous topic :: View next topic » |
Author |
Message
|
hivetri |
Posted: Wed Jan 31, 2018 6:22 am Post subject: Batch calling MQPUT1 and MQGET errors with MQRC 2018 |
|
|
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 |
|
 |
Vitor |
Posted: Wed Jan 31, 2018 7:05 am Post subject: Re: Batch calling MQPUT1 and MQGET errors with MQRC 2018 |
|
|
 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 |
|
 |
hivetri |
Posted: Wed Jan 31, 2018 1:57 pm Post subject: Re: Batch calling MQPUT1 and MQGET errors with MQRC 2018 |
|
|
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 |
|
 |
gbaddeley |
Posted: Wed Jan 31, 2018 3:44 pm Post subject: |
|
|
 Jedi Knight
Joined: 25 Mar 2003 Posts: 2538 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 |
|
 |
hivetri |
Posted: Wed Jan 31, 2018 7:22 pm Post subject: |
|
|
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 |
|
 |
Vitor |
Posted: Thu Feb 01, 2018 5:53 am Post subject: |
|
|
 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 |
|
 |
fjb_saper |
Posted: Thu Feb 01, 2018 6:45 am Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
And please add an MQCLOSE to that wrapper...  _________________ MQ & Broker admin |
|
Back to top |
|
 |
Vitor |
Posted: Thu Feb 01, 2018 7:06 am Post subject: |
|
|
 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 |
|
 |
RogerLacroix |
Posted: Thu Feb 01, 2018 1:28 pm Post subject: |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
|
Back to top |
|
 |
hivetri |
Posted: Tue Feb 06, 2018 5:11 am Post subject: |
|
|
Newbie
Joined: 31 Jan 2018 Posts: 4
|
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 |
|
 |
|
|
 |
|
Page 1 of 1 |
|
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
|
|
|
|