MQSCX functions

MQGem recently delivered a new version of MQSCX that supports the new IBM MQ V9 release. As well as support for the new command level, there were a number of other features in this new version of MQSCX. One of those new features was a popular customer request for the addition of functions to the MQSCX control language.

MQSCX FunctionsThere are some new examples available in our Example Scripts bundle, which demonstrate how to use functions. In this blog post we’re going to take a look at one of those samples, conns.mqx as a way to introduce you to functions. This function evolved from an earlier blog post, MaxChannels vs DIS QMSTATUS CONNS where it was used to demonstrate all the different ways application connections show up in a queue manager.

The first thing to notice comparing the script in the earlier blog post, to the one in the sample download, is that the code is topped and tailed by the following statements:-

func conns()
:
endfunc

This is how you define a function in the MQSCX control language. All the statements in between the func and endfunc statements make up the body of your function.

If you load up the sample into MQSCX by importing the file, and then show the contents of the function with the =show func(conns) list command, you’ll also see that the comments that immediately precede the function in the imported file are included in this display. A handy place to describe what your function does to remind you in the future.

MQSCX Extended MQSC Program – Version 9.0.0

Licenced to Paul Clarke

[16:58:24] =import file(C:\MQGem\MQSCX\conns.mqx)

[16:58:32] =show func(conns) list

***********************************************************************

* Function : conns *

* Purpose : Print out the current state of connections to the QM *

***********************************************************************

func conns()

 

=echo resp(no)

You can run the function simply by typing its name on the command line.

[16:58:32] conns

Total connections: 23

Local : 21

QMgr Chls : 0

Client Chls: 2

 

Total Running Channel instances: 1

QMgr Channels: 0

Client Channels: 1

MQG1>

The next comparison to make between this function and it’s original form in the earlier blog post, is use of the =echo statements. The intention of this script (in both cases) is that you don’t see all the commands and responses going to and from the command server, you just see the final totals printed on the screen. For the original script this meant at the start it switched off commands and responses, and then at the end, switched them back on again.

=echo cmds(NO)
=echo resp(NO)
:
=echo cmds(YES)
=echo resp(YES)

This would have the slightly undesirable effect that if you had either of those turned off before you ran the script, the script would inadvertently turn them back on again when it was done!

In the new version where the script is wrapped into function, there is only one =echo statement at the top.

=echo resp(NO)

There is no need to switch responses back on again because the =echo statement only applies inside the function. The function is a black box to any callers. It doesn’t impact any settings, such as these =echo settings, on the caller. Also notice that the default inside a function is that the commands are not shown anyway.

Functions aren’t just handy for wrapping your scripts into handy re-usable chunks, but also functions are very useful when they are parameterised. In this blog post we’re going to make some changes to the supplied conns() function to add a parameter. At the moment it totals all your connections. Now we’ll give it a parameter of an application name (or part of one) and it can total just those connections.

To indicate that a function has a parameter, the parameter name goes between the parentheses on the func conns() statement. When you later refer to that parameter in your script statements within the function you prefix it’s name with the ‘@’ symbol to show that it is a user variable.

func conns(ApplTag)
  :
  @ApplTag ...

In the MQSCX control language, parameters are not mandatory. We are still allowed to call the conns() function without giving it a parameter – if we code it that way. This would be a handy thing to have; without a parameter it totals everything, with a parameter it filters the totals by that application.

The way to achieve this – to have a parameter that can be optional – is to ensure that everywhere the parameter is used is preceded by a test to see if it exists. Now, I want to use the parameter more than once; first to check it against the APPLTAG that comes back from a DISPLAY CONN command, and then to check it against the RAPPLTAG that comes back from a DISPLAY CHSTATUS command. So rather than checking it exists multiple times, right up front I’ll test it and set it to a useful value if it doesn’t exist.

if (!exists(@ApplTag))
  @ApplTag = ""
endif

Now I can use the @ApplTag variable throughout the rest of the function with impunity.

In the old version of the script it just counted the totals that came back from a command issued to the command server – now it needs to look at the output to see whether the APPLTAG attribute contains the string supplied in the parameter. So let’s replace the initial two display commands with the following:-

@localconns = 0
@chlconns   = 0
foreach(DISPLAY CONN(*) CHANNEL APPLTAG)
  if (findstri(APPLTAG, @ApplTag))
    if (CHANNEL)
      @chlconns = @chlconns + 1
    else
      @localconns = @localconns + 1
    endif
  endif
endfor

Clearly if you ask to filter by an application name, none of the queue manager channel connections are going to match, but this code will still work when we don’t want to filter by anything because the findstri function returns TRUE when asked if the string contains the empty string.

N.B. findstri is the case insensitive version of findstr.

We also make a little tweak to the print out of the first line to reflect the use of the parameter by the user running the function.

And finally, the pre-existing foreach loop needs a little tweak. The DISPLAY CHSTATUS command is extended to also return the RAPPLTAG attribute, and then an if statement is added just as with the earlier for loop.

foreach(DISPLAY CHSTATUS(*) CURSHCNV CHLTYPE RAPPLTAG WHERE(STATUS EQ RUNNING)
  if (findstri(RAPPLTAG, @ApplTag))
    if (CHLTYPE = "SVRCONN")

Clearly you could take these changes even further, perhaps adding a parameter to configure a detail level for the output, with high detail showing all the channel names. The possibilities are endless. We hope you find functions a very useful addition to your MQSCX scripts.

Here’s the final view of the updated function with all the changes described in this post.

***********************************************************************
* Function : conns                                                    *
* Purpose  : Print out the current state of connections to the QM     *
***********************************************************************
func conns(ApplTag)

  if (_connqmgr = '')
    print 'Please connect to your queue manager before issuing "conns"'
    return
  endif

  if (!exists(@ApplTag))
    @ApplTag = ""
  endif

  @localconns = 0
  @chlconns   = 0
  foreach(DISPLAY CONN(*) CHANNEL APPLTAG)
    if (findstri(APPLTAG, @ApplTag))
      if (CHANNEL)
        @chlconns = @chlconns + 1
      else
        @localconns = @localconns + 1
      endif
    endif
  endfor

  if (@ApplTag)
    print 'Total connections containing "',:n:@ApplTag,:n:'":',@localconns + @chlconns
  else
    print 'Total connections:',@localconns + @chlconns
  endif
  print '   Local      :',@localconns

  @total = 0
  @svrcn = 0
  foreach(DISPLAY CHSTATUS(*) CURSHCNV CHLTYPE RAPPLTAG WHERE(STATUS EQ RUNNING)
    if (findstri(RAPPLTAG, @ApplTag))
      if (CHLTYPE = "SVRCONN")
        @svrcn = @svrcn + 1
        @total = @total + CURSHCNV
      endif
    endif
  endfor
  print '   QMgr Chls  :',@chlconns-@total
  print '   Client Chls:',@total
  print
  print 'Total Running Channel instances:',_matches
  print '   QMgr   Channels:',_matches - @svrcn
  print '   Client Channels:',@svrcn

endfunc

If you are a current MQSCX licence holder, you can simply download the new version of MQSCX and start using it. If you’re not a current licence holder, and you’d like to try out MQSCX, please email support@mqgem.com to request a trial licence.

Advertisements

The team at MQGem would love to hear what you think. Leave your comments here.

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s