section of the MQSeries documentation. In particular, this document will primarily explain how to interpret the above documentation, and thus use this particular implementation in perl. Please read and understand the following sections of the above document:

This interface also supports the text-based MQSC format messages used by the queue manager of some platforms, particularly MVS. Using the same interface, either PCF or MQSC command server can be queried, with the results translated into the same format for responses as well. Note that there are limits to how transparent this is (see MQSC NOTES), but the code tries quite hard to hide as many of the differences as possible.

Before we discuss the specific arguments and return values of each of the methods supported by the MQSeries::Command module, we must explain how the keys and values used by the interface were chosen, as this will allow the developer to understand how to take advantage of the very complete documentation provided by IBM (which will not be reproduced here).

For each command documented in 'Definitions of the Programmable Command Formats' (there is a specific page listing all of the commands, grouped by type), there is a corresponding method in this class. For example, there is a method named 'InquireQueueManager', for the obvious (I hope) PCF command.

All of these methods take a hash of key/value pairs as an argument, with the keys being those defined in the documentation for each command. When writing C code to produce PCF messages, the parameter names are macros, such as:

MQIACF_Q_MGR_ATTRS

to specify a list of queue manager attributes. Rather than use these names directly, the key strings are taken from the IBM documentation. In this example, the string used for this key is:

QMgrAttrs

The values depend on the structure type of the parameter. If the structure is a string (MQCFST), byte string (MQBACF) or an integer (MQCFIN) then the value of the key is simply a scalar string or integer in perl. If it either a string list (MQCFSL) or an integer list (MQCFIL), then the value of the key is an array reference (see the InquireQueueManager example in the SYNOPSIS) of scalar strings or integers.

Most of the individual methods map to underlying commands which do not return any data. For all of these, the return value is simply Boolean; true or false. That is, the command either worked or failed.

Only the methods associated with those commands documented as producing data responses:

return interesting information. Most of these will return an array of hash references, one for each object matching the query criteria. For example. The specific keys are documented in the section of the IBM documentation which discusses the "Data responses to commands", on the summary page "PCF commands and responses in groups". If you have read the IBM documentation as requested above, you should have found this page.

Note that in an array context, the entire list is returned, but in a scalar context, only the first item in the list is returned.

Some of these commands, however, have a simplified return value. All of the below:

This argument specifies the queue manager to which commands are to be sent.

If the 'ProxyQueueManager' argument is specified, this should be the name of the target queue manager.

If the 'ProxyQueueManager' argument is not specified, this can either be an MQSeries::QueueManager object, or the name of the Queue Manager. Specifying the queue manager name is deprecated and may stop working in a future release.

The 'QueueManager' argument can be omitted, in which case the "default queue manager" is assumed.

The name of the queue manager to which to MQCONN(), and submit messages on the QueueManagers behalf. This is to be used if a direct connection to the QueueManager is not possible, for example MVS queue managers with support for direct client access.

The messages will be put to what is assumed to be a remote queue definition which routes to the command queue on the desired QueueManager.

In order to specify the "default" queue manager as the ProxyQueueManager, an empty string must be explicitly given.

If a remote queue manager is controlled through a proxy, by having the QueueManager parameter specify the proxy and the CommandQueueName an object descriptor, then by default any output will print the queue manager name incorrectly. The RealQueueManager parameter specifies the name used for display purposes.

The ReplyToQ can be opened by the application, and the MQSeries::Queue object passed in to the MQSeries::Command constructor, if so desired, os, a fixed queue name can be given. This is a somewhat advanced usage of the API, since the default behavior of opening a temporary dynamic queue under the covers is usually prefered, and much simpler.

The responses are retrieved from the reply queue using gets by CorrelId, so there should be no issue with using a pre-defined, shared queue for this, if so desired.

For complex set-ups, where a remote queue manager is managed by the name of the command queue does not fit the standard scheme, the command queue can be opened manually and specified in the MQSeries::Command constructor as the CommandQueue parameter.

The CommandQueue parameter must be combined with the RealQueueManager parameter. In the example below, a mainframe queue manager CSQ1 is managed from the queue manager UNIXQM with a non-standard queue name:

This argument is introduced mainly to support the new PCF commands in MQ v6 (such as FilterCommand filter options) and to use PCF with QueueManagers on OS/390. It indicates the required PCF Command Version (MQCFH_CURRENT_VERSION) and Type. This is an optional argument and Version "1" is used as default. If a value '3' or higher is specified, then the Command Type "MQCFT_COMMAND_XR" will be used and also the version is set to "MQCFH_CURRENT_VERSION". Any value less then 3 will be ignored and the defaults are used (MQCFT_COMMAND and default version).

This value is used as the MQMD.Expiry field on all requests sent to the command server. The value is passed to the MQSeries::Message constructor, and should specify the time in tenths of a second. The default is 600, or 60 seconds.

A symbolic value ending on 's' for seconds or 'm' for minutes may also be specified, e.g. the symbolic value '45s' will have the same meaning as the number 450.

This value is used as the Wait argument to the MQSeries::Queue->Get() method call made against the ReplyToQ (a dynamic reply queue). and should be a time specified in milliseconds. The default is 60000, or 60 seconds.

A symbolic value ending on 's' for seconds or 'm' for minutes may also be specified, e.g. the symbolic value '45s' will have the same meaning as the number 45000.

NOTE: Both the Expiry and Wait defaults may be too slow for heavily loaded queue managers. Tune them appropriately.

The ReplyToQMgr normally defaults to the QueueManager, but it can be overridden, perhaps as a means of specifying an alternate return path over a specific channel. For example, the author uses special channels for SYSTEM related traffic, over which we forward MQSeries events from one queue manager to another, and also over which we wish the command server queries to flow.

The "default" path between QMA and QMB flows over a channel called QMA.QMB, but this traffic is application data, not administrative system data. The system queries flow over QMA.QMB.SYSTEM, and we need to ensure that replies to queries follow a similar reverse path. Specifying the ReplyToQMgr as "QMB.SYSTEM" accomplishes this.

This key specifies a code reference to a routine to replace all of the carp() calls in the API, allowing the user of the API to trap and handle all of the error message generated internally, or simply redirect how they get logged.

If this argument has a true value, then strict mapping of PCF parameters and values will be enforced. Normally, if you feed a bogus string into the API, it will attempt to map it to the underlying PCF macro value, and if the mapping fails, it will quietly forgive you, and ignore the parameter. Enabling this feature will cause the translation of an encoded PCF message into the data structure for a Response, or the translation of a Request into an encoded PCF message, to fail if any of the mappings fail.

Usually, the command server will generate errors if you feed bogus data into the API. but that will only occur after the data has been encoded and sent to the command server. This feature will allow you to detect this error before the data is ever sent.

This method will return different strings depending on whether the command is MQSC or PCF. For MQSC, the command server sends back some text explaining the reason code, and for PCF, we simply call MQReasonToText on the reason code and return that instead.

MQSC sends back far less information encoded into the reason than PCF does, and the interesting information is usually found in the ReasonText. Therefore, this method should be used when raising exceptions, in order to get the most descriptive explanation for any given error.

Normally, the data of interest is returned from the method in question, but the individual responses are available via this method. This returns a list of MQSeries::Command::Response objects, one for each individual message recieved.

This method will return a list of parameters structures from all of the responses messages sent back which were not error responses. Some errors will send back responses with parameters, and these could easily be confused with real data (until you start looking at the actual data, of course).

This method will return a list of parameters structures from all of the responses messages sent back which were error responses. If a command fails, the Reason() will usually tell you enough about the cause of the failure, but if the reason is MQRCCF_CFIN_PARM_ID_ERROR, then the parameters in the error message will indicate which Parameter key was invalid.

In some cases, it is useful or necessary to override specific MQMD fields in outgoing request messages. Examples include manually changeing the Persistence field, or changing the message identity or origin context. The MsgDesc method allows you to do so:

The key/value pairs in the Attrs argument are passed directly to the corresponding CreateQueue(), CreateChannel(), or CreateProcess() method. However, there is more to this than just creating the object. For clarity, this discussion will use creation of a queue as an example.

First, InquireQueue is called to see if the object already exists. If it does not exist, then the object is simply created, with the specified attributes.

If it does exist, and the QType matches, then the actual object attributes are compared against those passed to the CreateObject method, and if they match, then no action is taken, and the object is not modified.

If it does exist, but of a different QType, then the existing object is deleted, and the new object created as requested.

The idea here is to match the modification of the object conditional on the need for modifying the object. If the same CreateObject method call, with the same arguments, is called twice, then the second method invocation should be a noop, as far as the actual MQSeries object is concerned.

As discussed above, this is a HASH reference, whose key/value pairs are used to determine what type of object is being created or updated, and those key/value pairs are passed as-is to the appropriate Create* method call for the specified MQSeries object type.

Normally, when a Local queue is being replaced with another QType (eg. Remote or Alias), then the Local queue is not cleared before being deleted. If there are messages on the queue, this will cause an error. If the queue needs to be cleared, then this key must be passed with a true value.

This is a seperate option due to the inherit danger of destroying data accidentally. If you really want to clear the queues before recreating them as another QType, you will have to be explicitl about it.

This option will be passed to the Change* method, if the object already exists and is of type Queue, forcing changes to be applied to objects which are currently in use. It is ignored for the other object types. Note that this should not be passed as a key to the Attrs hash, since this is not really an object attribute.

If Force is given as an Attrs key, and the underlying Create* method is called, since the object does not already exist, then the command server will return an error.

This optional argument allows you to provide an object comparison subroutine, instead of relying on the built-in function. This is virtually never required, unless your request contains some 'meta' attributes that translate to multiple or different MQSeries attributes.

The Callback parameter must be a reference to a subroutine that receives three parameters: a reference to the requested attributes, a reference to the attributes found in the object, and a reference to a subroutine that compares two single attribute values. The return value from the subroutine must be a reference to a hash with those attribute names and values that actually should be changed.

Please see the source code of MQSeries::Command, specifically the _CompareAttributes method, for the default callback. Any callback you provide must behave in a similar way.

This section is NOT intended to replace the IBM "MQSeries Programmable System Management" documentation, and it merely serves to document the specific keys and values used by the perl implementation of the API.

In all cases, the keys which can be passed to the command are identical to the strings found in the documentation. However, some of the values also have more convenient string mapping as well, as these are not easily intuited by reading IBMs docs, thus these are clarified here.

The IBM docs list the possible values for each key as a list of MQSeries C macros (eg. MQCHT_SENDER), and if given, these will be respected. It will be faster to use the strings given, since these map directly to the actual macro values via a hash lookup, rather than a function call (all of the various C macros are implemented as function calls via an AUTOLOAD). Also, the author finds the replacement strings far more readable. YMMV.

The value must be an ARRAY reference of scalar values, all of which must be interpretable as strings.

NOTE: Some of the parameters (for example, the MsgExit parameter for the various Channel commands) can take either a string or string list. In this case, the API will be forgiving, and try to determine what you meant automatically. If you pass a reference, it will create a string list parameter, and if you pass a plain scalar, it will create a string.

ANOTHER NOTE: if you pass a simple scalar string where a string list is explicitly required (as opposed to optional), then the API will create a list of one string for you.

The value must be an ARRAY reference of scalar values, all of which must be interpretable as integers. As with the integer format, in some cases, a table will show a mapping from more readable text strings to the macros documented in the IBM manuals.

The value given need only be 0 or 1. This was done for some of the integer types which are documented to take a pair of macros, whose values were simply zero or one, and when the true/false nature of the key was considered to be intiuitive. For example, "DataConversion" is either on (true) or off (false).

Note: List of keys are not documented anymore to avoid needless redundancy. Please refer to the IBM documentation for the names and values of keys.

There are several commands which return data. The return value of the actual command methods depends on the specific command. All of the "Inquire*Names" commands return a list of the actual names returned, which greatly simplifies the parsing of the return value.

For example:

@qnames = $command->InquireQueueNames( QName => 'FOO.*' );

will result in @qnames containing a list of strings of all of the queue names starting with FOO.

The rest of the commands return a list of Parameters HASH references, extracted from each of the messages sent back from the command server. In a scalar context, only the first Parameters HASH reference is returned. Refer to the "RETURN VALUES" section for the list of commands.

For PCF requests to MQ v6 and above, filter commands can be used to have the queue manager filter out only objects of interest. For example, you can inquire for queues with a certain maximum message length, for connections from specific IP addresses, or for queue status with a minimum queue depth.

Filters require that the command object is created with CommandVersion 3, i.e.

Following that, most Inquire commands accept an optional FilterCommand parameter that specifies an attribute to filter on, a comparison operator, and a value. (See the IBM documentation for which Inquire commands support filters.)

The supported filter parameters (field names) are almost any field returned by the Inquire command (see the IBM documentation for details). The supported value can be an integer, string, string wildcard (a value ending on a '*'), or (for enumerated types) the constant name as returned by the Inquire command. For example, for an enumerated type, to query for alias queues that have a rmote queue as their base type:

The operators supported depend on the parameter type. All types support equal (==) and unequal (<>, !=); numeric types also support the numeric comparators (<, >, <=, >=); string types support 'like' and 'not like' with a wildcard value ending on '*'; integer list types support 'contains' and 'excludes'; and string list types support 'contains', 'excludes', 'contains_gen' and 'excludes_gen', where the latter to values perform a wildcard comparison. The examples below illustrate supported usage.

Note that the filter is not evaluated as a perl expression. The MQSeries::Command class parses the expression into a parameter, operator and value; then converts the value to the appropriate type (a value lookup for enumerated types, a conversion to integer for numbers, and conversion to string for strings). In other words, the expected amount of DWIM is in place.