Solved

CWBX .NET Message Queue

Posted on 2013-01-18
9
297 Views
Last Modified: 2014-11-05
Hi,
First of all i'm not an expert on as400 OS/command.
I building a prgm in.NET that would monitor DSPMSG MSGQ(QSYS/QSYSOPR)
I tryed to use cwbx.DataQueue object but an error is raised tell me that it can't found DQ QSYSOPR on Library QSYS. Ok now i know that a DataQueue is not a Message Queue ;-) .
But, i wonder if it i can use any other object on CWBX to retreive the content of this MSGQ ?
May be using cwbx.Program object ? if so how can  i retreive the output parameters to get the list of all messages ?

OS400 V5R2M0
VB.NET 2005
Windows 7

Thanks in advance.
Laurent
0
Comment
Question by:Laurent .
  • 4
  • 4
9 Comments
 
LVL 34

Expert Comment

by:Gary Patterson
ID: 38794694
.NET isn't great for this task, if you ask me.  IBM provides great tools for Java in the JTOpen project and in the functionally identical IBM Toolbox for Java, so if that is an option, do that:

JTOpen project: http://jt400.sourceforge.net/
http://javadoc.midrange.com/jtopen/com/ibm/as400/access/MessageQueue.html

Dealing with messages without using the Java classes is a pain.  The native API (QMHRTVM) is rather complex:

http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=%2Fapis%2Fmh1.htm

There is a slightly less complex command that you can use called RCVMSG:

http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=%2Fcl%2Frcvmsg.htm

If Java isn't an option, post back and I can give you some pointers.  Just be aware that this isn't a beginner task except in Java.

- Gary
0
 
LVL 27

Expert Comment

by:tliotta
ID: 38795309
IMO, the first step should be to decide if it's a good idea. Generally, the QSYSOPR message queue is not an object that ought to be allocated to a process running off-system. That's true of most objects named starting with "Q*". 'Normal' user message queues would usually be no problem, but QSYSOPR is one that has special meaning to the system itself.

A far better project would be to create a process that runs on the AS/400 to act as middleware. It would do any send/receive operations against QSYSOPR and relay to your .NET process. Data queues would be an excellent communications method between .NET and intermediate function.

Having the intermediary would allow creating methods that could be accessed and controlled by other processes on the AS/400. It would give capability of telling the intermediary to relinquish control when it becomes necessary, as well as other potential actions. That might be much more difficult if a networking issue suspends control from the .NET side.

It's certainly possible to build a .NET function as you seem to want, though I don't know of a direct API for it. It's just potentially a troublesome object to allocate in the way it would need to be done.

Tom
0
 

Author Comment

by:Laurent .
ID: 38799654
@Tom, @ Gary
Thank you guys for your feedback.
Well, since i prefere not put my nose on a JAVA for the moment, i'm a little bit in the rush so that would be the last option to me, i'm not a native JAVA dev...yet.

May be i need to come back to my original reason why i did open this thread. We have a System iSerie 9406-800, with OS400 V5R2 running MOVEX 10A and DataMirror v2.3 (To a SQL Server DB). Our Storage(HDD) is full at 75%, we can't upgrage it without upgrade the OS, we can't upgrade the OS without upgrade MOVEX/DataMirror. Our group have a plan to switch to SAP in 2014 so the upgrade is not a solution. MOVEX 10A has some knowed bugs, since we do not have support anymore on MOVEX, we have to deal with the situation.
Problem is, some time to time, i have some MOVEX prg that generate some messages on QSYSOPR MSGQ that required a reply.
In order to be as much responsive as possible, i was looking for solution to trigger an alert each time such messages are queued.

IBM Support provide me with a CL prg to send SMTP msg for each critical message (i put the code in attachment for further reference). I didn't test it yet, i would need some help from IBM to test it.
As Tom said, a server side middleware looks be a better solution for the moment.
I will post the result of this prg once tests have been done.

Thanks again to both to pointing me to the right direction.

Laurent
0
 
LVL 27

Accepted Solution

by:
tliotta earned 500 total points
ID: 38800815
At V5R2, it's harder to be sure. Is there a reason you never went to V5R3?

I could do some testing at V5R3, but I can't determine V5R2 details. At V5R3, I'd use Management Central to monitor disk utilization. I think it's reasonably similar for V5R2.

But at V5R3 (and possibly V5R2), the messages don't have to go to QSYSOPR. They can go to a number of message queues (or users). See the Change Service Attributes (CHGSRVA) command to see message queues configured for it, and see system value QSTGLOWACN to see if it is set to *CRITMSG or *REGFAC. The <Help> text for both will give some guidance. With QSYSOPR out of the way (or simply one of a list of queues), a number of message handling options are less intrusive.

Other options exist besides Management Central and service messaging. In some rare cases, you might even have the AS/400 use NET SEND to send messages over the Windows Messenger service. (Not "NET SEND" but an API that does the work.) Almost all local networks block Messenger messages at the routers, and it's disabled by default at workstations nowadays, but it can be handy for some simple uses.

Tom
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 

Author Comment

by:Laurent .
ID: 38808270
@Tom: Thanks for the reply, i will investigate this way too.
0
 

Author Comment

by:Laurent .
ID: 38808277
just see that the attachment didn't work on my post from Jan-21th, so here the code of the prg that monitor critial message and perform an action. NEED TO BE CUSTOMIZED.
@courtizy of IBM Vienam

PGM

/*-------------------------------------------------------------------*/
/* Declare the month, day, etc.                                      */
/*-------------------------------------------------------------------*/
             DCL        VAR(&MONTH) TYPE(*CHAR) LEN(2)
             DCL        VAR(&DAY) TYPE(*CHAR) LEN(2)
             DCL        VAR(&YEAR) TYPE(*CHAR) LEN(4)
             DCL        VAR(&TIME) TYPE(*CHAR) LEN(8)
             DCL        VAR(&HOUR) TYPE(*CHAR) LEN(2)
             DCL        VAR(&MIN) TYPE(*CHAR) LEN(2)
             DCL        VAR(&SEC) TYPE(*CHAR) LEN(2)

/*-------------------------------------------------------------------*/
/* The variables used to get the values from retrieve system value   */
/*                                                                   */
/* The QDATETIME is returned as this according to the help text :    */
/* The format of the field is YYYYMMDDHHNNSSXXXXXX :                 */
/*  YYYY is the year                                                 */
/*  MM is the month                                                  */
/*  DD is the day                                                    */
/*  HH is the hours                                                  */
/*  NN is the minutes, SS is the                                     */
/*  SS is the seconds                                                */
/*  XXXXXX is the microseconds                                       */
/*                                                                   */
/* DATFMT is the format of the date such like  YMD, MDY, DMY, JUL    */
/*-------------------------------------------------------------------*/
             DCL        VAR(&QDATETIME) TYPE(*CHAR) LEN(20)
             DCL        VAR(&QDATFMT) TYPE(*CHAR) LEN(3)

/*-------------------------------------------------------------------*/
/* Misc variables                                                    */
/*-------------------------------------------------------------------*/
             DCL        VAR(&HEADER) TYPE(*CHAR) LEN(3)
             DCL        VAR(&POS) TYPE(*DEC) LEN(3)
             DCL        VAR(&SEVERITY) TYPE(*CHAR) LEN(2)
             DCL        VAR(&SEV#) TYPE(*DEC) LEN(2)
             DCL        VAR(&HEADERFND) TYPE(*CHAR) LEN(1)

/*-------------------------------------------------------------------*/
/* Declaring a file to import the output of the history log          */
/*-------------------------------------------------------------------*/
             DCLF       FILE(QTEMP/QHIST)

MAIN:

             RTVSYSVAL  SYSVAL(QDATFMT) RTNVAR(&QDATFMT)                /* Retrieving date format */

             DLTF       FILE(QTEMP/QHIST)                               /* Recreating the temp file used */
             MONMSG     MSGID(CPF0000)                                  /* for importing the hist log    */
             CRTPF      FILE(QTEMP/QHIST) RCDLEN(132) SIZE(*NOMAX)

/*-------------------------------------------------------------------*/
/* Here we are getting the datetime from retrieve system value       */
/* Then we break down the hours/mins/secs                            */
/* and we put it in a format of 'HH:MM:SS' to pass to the dsplog cmd */
/*-------------------------------------------------------------------*/
             RTVSYSVAL  SYSVAL(QDATETIME) RTNVAR(&QDATETIME)
             CHGVAR     VAR(&HOUR) VALUE(%SST(&QDATETIME 9 2))
             CHGVAR     VAR(&MIN) VALUE(%SST(&QDATETIME 11 2))
             CHGVAR     VAR(&SEC) VALUE(%SST(&QDATETIME 13 2))
             CHGVAR     VAR(&TIME) VALUE(&HOUR *CAT ':' *CAT &MIN *CAT ':' *CAT &SEC)

/*-------------------------------------------------------------------*/
/* We dump the history log and will copy it over to our file that we */
/* declared, QHIST in library QTEMP                                  */
/* Then we delete the spoolfile                                      */
/--------------------------------------------------------------------*/
DMPLOG:
             DSPLOG     PERIOD((&TIME)) OUTPUT(*PRINT)

             MONMSG MSDID(CPF0000) EXEC(DO)                             /* OK here what can happen is we can   */
                CHGJOB     LOG(*SAME *SAME *NOLIST)                     /* get an error saying that we can't   */
                SBMJOB     CMD(call histmon) JOB(HISTMON) +             /* spool anymore, if we spool too many */
                          JOBQ(QSYSNOMAX)                               /* times. Submit another monitor job   */
                RETURN                                                  /* and end cleanly                     */
             ENDDO

             CPYSPLF    FILE(QPDSPLOG) TOFILE(QTEMP/QHIST) +
                          SPLNBR(*LAST)
             DLTSPLF    FILE(QPDSPLOG) SPLNBR(*LAST)

/*-------------------------------------------------------------------*/
/* The way this works is we need to scan the history for the the word*/
/* SEV like in the below example. The SEV in                         */
/*                                                                   */
/* 5761SS1 V6R1M0 080215                                History Log  */
/*MSGID    SEV MSG TYPE                                              */
/*CPA4067  99  INQUIRY      Save file MCASE in MCASE already contains*/
/*                                                                   */
/* After we find the SEV header, we can now scan the file for that   */
/* position on the next lines for the severity level                 */
/*-------------------------------------------------------------------*/
             CHGVAR VAR(&POS) VALUE(0)
             CHGVAR VAR(&HEADERFND) VALUE('0')
READF:
             RCVF
             MONMSG     MSGID(CPF0864) EXEC(GOTO EXITREAD)              /* End of file, exit to  */
                                                                        /* EXITREAD              */

             IF COND(&HEADERFND *EQ '0') THEN(DO)                       /* Find the header first */
FINDHDR:
                CHGVAR VAR(&POS) VALUE(&POS + 1)
                IF COND(&POS *GT 129) THEN(DO)
                   CHGVAR VAR(&POS) VALUE(0)
                   GOTO READF
                ENDDO
                CHGVAR VAR(&HEADER) VALUE(%SST(&QHIST &POS 3))
                IF COND(&HEADER *EQ 'SEV') THEN(DO)
                   CHGVAR VAR(&HEADERFND) VALUE('1')
                   GOTO READF
                ENDDO
                GOTO FINDHDR
             ENDDO

             IF COND(&HEADERFND *EQ '1') THEN(DO)                       /* Now to check for severity on  */
                CHGVAR VAR(&SEVERITY) VALUE(%SST(&QHIST &POS 2))        /* the next lines of the histlog */
                CHGVAR VAR(&SEV#) VALUE(&SEVERITY)                      /* We convert the severity #     */
                MONMSG MSGID(CPF0000) EXEC(DO)                          /* character string to decimal   */
                   GOTO READF
                ENDDO
                IF COND(&SEV# *GT 50) THEN(DO)                          /* In this example, if the sev      */
                  SNDMSG MSG('got it!!') TOUSR(NNGUYEN)                 /* is greater than 50, do something */
                  RETURN
                ENDDO
              ENDDO

              GOTO READF                                                /* Continue reading the file */


/*-------------------------------------------------------------------*/
/* Get the current time so we can just dump the history for next     */
/* round. There is a chance we might miss a message but it should    */
/* slim chance                                                       */
/*-------------------------------------------------------------------*/
EXITREAD:
              RTVSYSVAL  SYSVAL(QDATETIME) RTNVAR(&QDATETIME)
              CHGVAR     VAR(&HOUR) VALUE(%SST(&QDATETIME 9 2))
              CHGVAR     VAR(&MIN) VALUE(%SST(&QDATETIME 11 2))
              CHGVAR     VAR(&SEC) VALUE(%SST(&QDATETIME 13 2))
              CHGVAR     VAR(&TIME) VALUE(&HOUR *CAT ':' *CAT &MIN *CAT ':' *CAT &SEC)

              CLOSE                                                     /* Close our temp file so we can */
                                                                        /* open it up again              */
              DLYJOB DLY(60)
              GOTO DMPLOG

END:
ENDPGM

Open in new window

0
 
LVL 27

Expert Comment

by:tliotta
ID: 38811662
I'm not sure what that program is supposed to do. It has a couple questionable parts that need to be examined.

For example, at line 71, the history log is dumped to a spooled file. The entries that are dumped are those beginning at the time specified in variable &TIME and ending at the current time. But the value in &TIME is set by retrieving the QDATETIME system value and extracting the time portion.

That means that all entries beginning at the current time and ending at the current time (because ending time defaults there) are dumped. The result should almost always be a CPF2447 *ESCAPE message saying that no entries exist.

And the result of that would be triggering the MONMSG at line 73 because it checks for the 'template' value of CPF0000 rather than a spool limit message. That causes the program to submit itself to QSYSNOMAX to start over again. And the result of that should be the same thing happening over again.

Also, it is reviewing the history log rather than a service message queue. That might be okay if you are only interested in history log entries. And given your description of your goal, that might be good enough.

But it needs a lot of work. There are numerous other things that would need changing if it is the start of what you want to do.

I would investigate the alternatives before going this way.

Tom
0
 
LVL 27

Expert Comment

by:tliotta
ID: 38811827
I'd look into Management Central first. If that wasn't satisfactory, I'd create a custom message queue monitor. Either way, I'd have my function running against an alternative service message queue that was created specifically for this purpose.

Tom
0
 

Author Closing Comment

by:Laurent .
ID: 40425548
Upgrade OS to V5R3 solved the issue
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

In this article, you will read about the trends across the human resources departments for the upcoming year. Some of them include improving employee experience, adopting new technologies, using HR software to its full extent, and integrating artifi…
A safe way to clean winsxs folder from your windows server 2008 R2 editions
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now