Problem with CPFA0A9 resolved

I was having problems with the sending of message CPFA0A9 which was received in an exception routine onto the message queue of our Receiver Apply Program. This stems from the message data which is sent being of type *CCHAR and CCSID 1200.

Initially we tried to convert the message data using the iconv() functions but had limited success and after posting on the iSeriesNetwork forums manged to identify the problem and possible solutions. Eventually we decided to use the optional CCSID parameter on the QMHSNDM API, this also required us to change the CCSID of the message queue from 65535 which is the default to 37 for our system! This could have been a problem further in the installation of the product because we would have to set the CCSID of this message queue as we installed it.

The problem then changed, we now saw some converted text in the message queue but not all of it. As the numbers didn’t ring any bells we logged a problem with IBM.
Here is the test program we supplied to IBM to show the results we were seeing.

#include                          /* Exception Handling */
#include                          /* Exception signals */
#include                        /* Change Error message */
#include                        /* Send Program Message */
#include                         /* Send Non Program Msg */
#include                         /* command execution */
#include                           /* Error Code Structs */
#include                           /* standard I/O */
#include                          /* standard I/O */
#include                          /* memory and string*/

typedef struct  EC_x {
                Qus_EC_t EC;
                char Exception_Data[1024];
                }EC_t;

static void rep_cmd_check(_INTRPT_Hndlr_Parms_T *excp_info) {
int *count = (int *)(excp_info->Com_Area);
int CCSID = 1200;                           /* CCSID CPFA0A9 */
char MsgQ[20] = "TESTMSGQ  *LIBL     ";
char Msg_Type[10] = "*INFO     ";           /* msg type */
char QRpy_Q[20] = {' '};                    /* reply queue */
char Msg_Key[4] = {' '};                    /* msg key */
char msg_dta[1024];                         /* message buffer */
EC_t Error_Code = {0};                      /* error code struct */

Error_Code.EC.Bytes_Provided = sizeof(Error_Code);

*count = 1;
printf("Message length %d",excp_info->Msg_Data_Len);
if(memcmp(excp_info->Msg_Id,"CPFA0A9",7) == 0) {
   QMHSNDM(excp_info->Msg_Id,
          "QCPFMSG   *LIBL     ",
          excp_info->Ex_Data,
          excp_info->Msg_Data_Len,
          Msg_Type,
          MsgQ,
          1,
          QRpy_Q,
          Msg_Key,
          &Error_Code,
          CCSID);
   if(Error_Code.EC.Bytes_Available > 0) {
      printf("Failed %.7s",Error_Code.EC.Exception_Id);
      }
   QMHCHGEM(&(excp_info->Target), 0,
           (char *) (&(excp_info->Msg_Ref_Key)),
           "*HANDLE   ","",0,&Error_Code);
    return;
   }
return;
}

int main(int argc, char** argv) {
volatile int e_count = 0;                   /* error flag */
char msg_dta[50];
char reply;
char cmd_str[255] = "RMVLNK OBJLNK('/home/c.hris/eclipse/RSE/SBM00002.log')";

#pragma exception_handler(rep_cmd_check,e_count,0,_C2_ALL,_CTLA_HANDLE)
QCMDEXC(cmd_str,strlen(cmd_str));
#pragma disable_handler

if(e_count > 0) {
   exit(-1);
   }
exit(0);
}


The message we saw in the message queue was partly converted with non printable characters following the correctly converted characters.

IBM advised us the problem was related to the exception data not being the entire message data, it is restricted to the first 48 bytes of the message data! We had missed that entirely, most of the messages we had processed in the past must have had message data less than 48 bytes! We had told the QMHSNDM API we were passing 78 bytes, it would pass on 37 bytes of converted data but we only saw 24 bytes of actual converted data in the message queue..

So as per IBM’s advice we coded up the exception routine to get the message data directly from the message itself, we took the decision to do this even if the message data was less than 48 bytes because with UTF-16 data (this is CCSID 1200) each character takes up 2 bytes, so in effect we would only process 24 characters of message data in UTF-16 in the exception routine. Also having been burned this time we didn’t want it to happen again with some other message we had yet to stumble upon.

IBM’s suggestion was to use the QMHRCVM API which turned out to be a double hit because it would automatically convert the data to the Job CCSID. The message queue could remain at CCSID 65535 with no side effects.

This is the code now.

#include                          /* Exception Handling */
#include                          /* Exception signals */
#include                        /* Change Error message */
#include                        /* Send Program Message */
#include                         /* Send Non Program Msg */
#include                        /* Recv Program Msg */
#include                          /* command execution */
#include                              /* Error Code Structs */
#include                               /* standard I/O */
#include                              /* standard I/O */
#include                             /* memory and string*/

typedef struct  EC_x {
                Qus_EC_t EC;
                char Exception_Data[1024];
                }EC_t;

typedef _Packed struct  Rcv_Msg_x {
                        Qmh_Rcvpm_RCVM0100_t msg_struct;
                        char msg_data[2048];
                        }Rcv_Msg_t;

static void rep_cmd_check(_INTRPT_Hndlr_Parms_T *excp_info) {
int *count = (int *)(excp_info->Com_Area);
char MsgQ[20] = "TESTMSGQ  *LIBL     ";
char Msg_Type[10] = "*INFO     ";           /* msg type */
char QRpy_Q[20] = {' '};                    /* reply queue */
char Msg_Key[4] = {' '};                    /* msg key */
char msg_dta[1024];                         /* message buffer */
Rcv_Msg_t rtv_dta;                          /* message struct */
EC_t Error_Code = {0};                      /* error code struct */

Error_Code.EC.Bytes_Provided = sizeof(Error_Code);

*count = 1;
QMHRCVPM(&rtv_dta,
         sizeof(rtv_dta),
         "RCVM0100",
         "*         ",
         0,
         "*ANY      ",
         (char *) (&(excp_info->Msg_Ref_Key)),
         0,
         "*SAME     ",
         &Error_Code);
if(Error_Code.EC.Bytes_Available > 0) {
   snd_error_msg(Error_Code);
   sprintf(msg_dta,"Failed to retrieve message data");
   snd_msg("GEN0001",msg_dta,strlen(msg_dta));
   return;
   }

QMHSNDM(excp_info->Msg_Id,
        "QCPFMSG   *LIBL     ",
        rtv_dta.msg_data,
        rtv_dta.msg_struct.Data_Returned,
        Msg_Type,
        MsgQ,
        1,
        QRpy_Q,
        Msg_Key,
        &Error_Code);
if(Error_Code.EC.Bytes_Available > 0) {
   snd_error_msg(Error_Code);
   sprintf(msg_dta,"Failed to send message");
   snd_msg("GEN0001",msg_dta,strlen(msg_dta));
   return;
   }
QMHCHGEM(&(excp_info->Target), 0,
         (char *) (&(excp_info->Msg_Ref_Key)),
         "*HANDLE   ","",0,&Error_Code);
return;
}

int main(int argc, char** argv) {
volatile int e_count = 0;                   /* error flag */
char msg_dta[50];
char reply;
char cmd_str[255] = "RMVLNK OBJLNK('/home/c.hris/eclipse/RSE/SBM00002.log')";

#pragma exception_handler(rep_cmd_check,e_count,0,_C2_ALL,_CTLA_HANDLE)
QCMDEXC(cmd_str,strlen(cmd_str));
#pragma disable_handler

if(e_count > 0) {
   exit(-1);
   }
exit(0);
}

Now you will get the correct message displayed in the message queue listed..

Hope this helps others out who have the same problems..

Chris…

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.