Changes.src

- Introduction
- Changes for 1.10
  - MQSeries::Command MQSC bugs
  - MQSeries::Message allows BufferLength of 0
  - MQSeries::Command->CreateObject enhancements and documentation
- Changes for 1.09
  - Support for Win32
  - Retry logic in MQSeries::QueueManager->Connect() and MQSeries::Queue->Open()
  - MQSeries::Command->new takes additional arguments.
  - MQSeries::Command->CreateObject() method added
  - MQSeries::QueueManager Hconn reference counting
  - MQSeries::QueueManager constructor arguments
  - MQSeries::Queue->Open() ignores the Hobj on errors
  - MQSeries::Message->Buffer() method added
  - MQSeries::Message::Event->GetConvert() saves raw Buffer
- Changes for 1.08
  - MQSeries::Message::Event was broken
  - MQSeries::Command error checking enhancement
  - MQSeries::QueueManager and MQSeries::Queue constructor bug
  - MQSeries::Queue->Put() method wasn't setting MQPMO_FAIL_IF_QUIESCING
  - MQSeries::PubSub::Broker/Stream API enhanced to support alternate users
- Changes for 1.07
  - MQSeries::Message::PCF memory leak
  - Change to simplify static compiles
  - Default Expiry values were wrong
- Changes for 1.06
  - MQSeries::PubSub::*
  - MQSeries::Message::PCF
  - MQSeries::Message::RulesFormat
  - MQSeries::Message::XML-Dumper
  - MQSeries::Command
  - MQSeries::QueueManager
  - MQSeries::Queue
  - MQSeries core module
  - Installation Procedures, and other Miscellany
- Changes for 1.05
  - Installation Procedures
  - MQSeries
  - MQSeries::QueueManager
  - MQSeries::Queue
  - MQSeries::Command
- Changes for 1.04
  - MQSeries
  - MQSeries::Command
  - MQSeries::Message::Storable
- Changes for 1.03
- Changes for 1.02

# Introduction

This file documents the changes to each and every release of the MQSeries perl API, going back as far as the 1.02 release.

# Changes for 1.10

## MQSeries::Command MQSC bugs

Thanks to yet another data length limitation, the string ``INITIALIZING'' is too long for OS/390 to display, so this gets truncated to ``INITIALIZI'', for output of the `InquireChannelStatus()` command, only on that platform. The API can parse this correctly now.

The IndexType values weren't properly mapped on either requests or responses. Now they are.

The HardenGetBackout paremeter was incorrectly encoded in MQSC. It is now.

## MQSeries::Message allows BufferLength of 0

This is one that came back to haunt me, as I thought I had fixed this way back in 1.04. If you attempt to create an MQSeries::Message with a BufferLength of zero, you actually get one with the default value of 32K. This is bad, if you are writing some code to say, browse a queue and just get all of the headers, as you end up getting some of the data, too. The code does the right thing now, and properly accepts a BufferLength of 0.

## MQSeries::Command->CreateObject enhancements and documentation

I added a new key (Clear) to indicate that when replacing a Local queue with another QType, the Local queue should be cleared before being deleted.

There are also a couple of examples in the SYNOPSIS section, and documentation for the new method call. This can now be considered production, and is no longer experimental. The author uses this call almost exclusively, in new development, for creating objects.

# Changes for 1.09

## Support for Win32

This release compiles on Windows NT 4.0, and has thus far been tested with ActiveState 5.00503, build 521, with Visual C++ 6.0. Other perl/compiler combinations will probably follow, but the initial support is all the author has to test. I've tested it with 5.0 as a client, and 5.1 as both client and server.

NOTE: (and a WARNING, too). This code determines where your MQSeries installation is by querying the Windows Registry, using Win32::TieRegistry. This is done not only at compile time (to find the includes files and shared libs), but also at run time to determine whether or not to use the client or server API, automatically.

## Retry logic in MQSeries::QueueManager->Connect() and MQSeries::Queue->Open()

The retry logic was always there in MQSeries::QueueManager->Connect(), but now it is much more configurable. You can specify which reasons codes are worth retrying, rather than depend on a hardcoded (and possibly wrong or incorrect) list.

MQSeries::Queue->Open() also support retry logic, and the author finds this very useful for daemons recovering from a previous crash, attempting to open a queue for exclusive input, and waiting for the previously invoked agent process to free up the input handle.

The documentation for both modules has a RETRY LOGIC section. See that for more information, as well as the documentation for the constructors, and each of the specific methods.

## MQSeries::Command->new takes additional arguments.

The MQSeries::Command constructor takes additional arguments allowing you to specify the Model Queue, and DynamicQName used to open the dynamic reply queue for command messages.

## MQSeries::Command->CreateObject() method added

WARNING: This new method, while being Very Cool, is EXPERIMENTAL, and intentionally not documented, as the API will likely change. It will probably stabilize in 1.10.

CreateObject is a higher level wrapper function that will only create the specified object if it doesn't exist, or the specified attributes don't match. This is a conditional object creation, that will be a noop if the object is already correctly configured.

## MQSeries::QueueManager Hconn reference counting

A global hash, keyed on the process ID, and the Hconn value, will keep track of how many MQSeries::QueueManager objects have been instantiated for a given queue manager connections (since the Hconn values get reused). The object destructor will now decrement these values, and only the last object will actually disconnect from the queue manager.

This is actually a significant enhancement, as it was possible to pre-maturely disconnect from the queue manager when instantiating lots of objects, all of them specifying the queue manager by name, and thus internally recreating lots of MQSeries::QueueManager objects. The first one to get destroyed would wipe out the connection, causing problems for the others.

## MQSeries::QueueManager constructor arguments

The constructor argument QueueManager can now be another MQSeries::QueueManager argument, and the QueueManager name will be stolne from that object, and a new one instantiated. This really just allows an MQSeries::QueueManager object to be passed to the MQSeries::PubSub::Broker constructor, actually.

## MQSeries::Queue->Open() ignores the Hobj on errors

The Hobj value returned by `MQOPEN()` is only saved in the object hash when the CompCode is either MQCC_OK or MQCC_WARNING. The value when there is a failure can be a large, useless negative number, but then this looks like a true value in perl.

This confuses the subsequent attempts to call ->Open(), which are supposed to return true if the object is already opened. This was done via:

            return 1 is $self->{Hobj};

which will be wrong. This is primarily relevant is you implement any form of retry logic for failed queue opens.

## MQSeries::Message->Buffer() method added

A new method to return the raw buffer from an `MQGET()` call. This is relevant for classes which use `GetConvert()` methods to translate the raw data into a customized form. If they save the raw buffer into $self->{Buffer}, then it will be available.

## MQSeries::Message::Event->GetConvert() saves raw Buffer

This `GetConvert()` method will save the raw buffer, which in this case gives the developer access to the raw PCF data. The author uses this to echo the original event, in its unaltered format, to other systems management packages, afte rhe gets to it first.

# Changes for 1.08

This is another relatively minor bug fix release, but since I'm releasing it internally at MSDW, I'm also releasing it to CPAN as well.

## MQSeries::Message::Event was broken

I made a global variable lexically scoped to its file with an erroneous ``my'' keyword. Don't do that. The Event parsing class was totally broken as a result.

## MQSeries::Command error checking enhancement

When a command fails, the `Reason()` was being set to the last reason code found in the returned messages, which is always 3008 (command failed). Now the code will catch the first non-zero return code, and default to that, and this reason code is usually the one you want.

For example, InquireQueue for a non-existent queue name will now return 2085 (object not found), instead of the generic and uninteresting 3008.

## MQSeries::QueueManager and MQSeries::Queue constructor bug

Although I don't recommend using this particular interface, the constructors for both of these classes allow you to pass scalar references for the Reason and CompCode, so that the `MQCONN()` or `MQOPEN()` errors, if any, can be obtained.

These were only being set if there was an error, and now they are set regardless. Thus, if you initialize the values to, say MQRC_UNEXPECTED_ERROR and MQCC_FAILED, they will be left that way.

Note that I highly recommend using the NoAutoConnect and NoAutoOpen arguments, and then error checking the ->Connect() and ->Open() methods explicitly. The resulting code is much cleaner, IM!HO.

## MQSeries::Queue->Put() method wasn't setting MQPMO_FAIL_IF_QUIESCING

The various `*_FAIL_IF_QUIESCING` options are set everywhere by default (as the author happens to beleive they should be), except here. This is fixed.

## MQSeries::PubSub::Broker/Stream API enhanced to support alternate users

In order to enable the development of adminstrative tools for Publish/Subscribe which allow me to age bogus subscriptions (i.e. subscriptions that point to non-existent queues), I needed to be able to DeregisterSubscriber as an alternate user ID.

The API was enhanced to expose a bit more of the underlying method calls in order to make this possible.

In addition, several minor bugs in the Administrative PubSub API were fixed, making it possible to get at almost all of the metatopic information easily.

# Changes for 1.07

This release is a minor bug fix release, but one of them is significant enough to justify a public release.

## MQSeries::Message::PCF memory leak

The MQDecodePCF routine didn't properly mortalize the references it returns. I hate it when that happens. The result was that long-running applications that used the Command API (or any of the PCF-based formats) heavily (guess what the author was developing when he discovered this? ;-) will leak memory heavily. This is fixed.

In addition, the same error was made in the MQSeries::Message::RulesFormat XS code as well, and that was also fixed.

Note that none of the basic MQI interfaces had any problems at all. There are now no known memory leaks anywhere in the XS code. We've had long running perl daemons up for weeks using the basic MQSeries interface, with no reported issues.

## Change to simplify static compiles

The obnoxious, er, I mean, very important and absolutely essential legal question about the LICENSE file will be asked only once. When compiling statically, the Makefile.PL gets run again, and if it blocks on input this is not only annoying, but it breaks the static compile.

## Default Expiry values were wrong

The default Expiry values used in the MQSeries::Command API were incorrect, having the same value as the WaitInterval. As you probably know, Expiry is tenths of a second, and Wait is milliseconds. Oops.

# Changes for 1.06

This release is the first to make it to CPAN (the Comprehensive Perl Archive Network), as the primary distribution mechanism, rather than IBM's proprietary Support Pac web site. In addition, this code is now copyrighted by MSDW (the author's employer) but released under a license which is based on the Perl Artistic License.

It is now truly Open Source. Viva the Revolution, baby...

## MQSeries::PubSub::*

The entire Publish/Subscribe API is new with this release. This includes the following modules:

MQSeries::PubSub::Command
  A base class for all of the Publish/Subscribe commands, this module is not used directly, but rather one of its two subclasses is.

MQSeries::PubSub::Broker
  This subclass of MQSeries::PubSub::Command, and MQSeries::QueueManager, implements an interface to the Broker-specific Publish/Subscribe commands.

  This module also supports an set of ``Extended Commands'', which are higher level interfaces to the contents of the administrative inforamtion in the metatopics.

MQSeries::PubSub::Stream
  This subclass of MQSeries::PubSub::Command, and MQSeries::Queue, implements an interface to the Stream-specific Publish/Subscribe commands.

MQSeries::PubSub::Message
  This subclass of MQSeries::Message::RulesFormat provides an interface for creating and parsing MQRFH-formated Publish/Subscribe messages.

MQSeries::PubSub::AdminMessage
  This quasi-subclass (not a *true* OO subclass, but who's looking) of MQSeries::Message::PCF provides an interface to the Publish/Subscribe administrative messages published in PCF format.

## MQSeries::Message::PCF

This is a new class which provides a much more generic interface to PCF messages. Prior to this release, there were several routines which parsed implementation-specific formats, with a lot of duplicated code.

This class can be used directly, but it was primary designed so that its two core functions (MQEncodePCF and MQDecodePCF) would be used as building blocks for the implementation-specific formats, such as Performance Events (MQSeries::Message::Event), Command server requests and responses (MQSeries::Command::*), and the Publish/Subscribe administrative messages (MQSeries::PubSub::AdminMessage).

## MQSeries::Message::RulesFormat

This is a new class which provides an interface to the MQRFH Rules and Format messages used by the Publish/Subscribe system. This can also be used to create messages for working with the NEON MQIntegrator 1.X product suites, since the format is the same, although the author hasn't actually tried this yet.

## MQSeries::Message::XML-Dumper

This is a new subclass of MQSeries::Message which encodes/decodes complex perl data structures using the XML-Dumper module. This was mostly done as a proof of principle, and to please some XML zealots.

Note that the parsing of XML is much more expensive than the Storable approach, and if you have a perl process on the sending and receiving end of a message flow, the author still recommends using Storable.

This requires the CPAN XML::Dumper and XML::Parser modules.

## MQSeries::Command

More complete documentation
  The various strings used to represent the PCF parameters and values have finally been documented, so someone other than the author may actually be able to use this code.

Extended to V5.1 PCF Commands
  All of the new Commands for V5.1 are supported, and in fact, even if you compile the MQSeries API with 5.0, you can still use the new commands, and parse the resulting PCF parameters. The code which maps numeric parameters to key strings has been ``flattened'' such that it doesn't use the actual C macros.

  These files (MQSeries/Command/PCF/*.pl) were auto-generated on an MQSeries 5.1 host, so the macro-to-number mapping has already been done, and it is not necessary for the C macro to have been compiled into constants.c.

Extended to V2.1 MQSC Commands
  Most, but not all, of the MQSC commands (i.e. commands sent to an MQSC-only command server, for example an MVS queue manager) have been supported, and the API can parse all of new V2.1 object attributes (like ``ALTDATE'' and ``ALTTIME'').

  WARNING: The MQSC code has not been extensively tested, so use it with caution.

## MQSeries::QueueManager

NoAutoConnect option
  The call to MQCONN is normally done in the constructor, but if it fails, the error checking semantics are ugly. A new option (NoAutoConnect) disables the implicit call to ->Connect(), and allows the developer to make this call, and error check it explicitly.

  The `Connect()` method is also new.

Inquire/MQINQ Support
  Method calls have added to support the `MQINQ()` call against the queue manager itself. This includes both `Open()` and `Close()` methods, which were not previously available.

  The `Open()` method is also new, although it is just a rename of the older semi-private `_mqopen()` method call.

## MQSeries::Queue

NoAutoOpen option
  The call to MQOPEN is normally done in the constructor, but if it fails, the error checking semantics are ugly. A new option (NoAutoOpen) disables the implicit call to ->Open(), and allows the developer to make this call, and error check it explicitly.

Inquire/Set MQINQ/MQSET Support
  Method calls have added to support the `MQINQ()` and `MQSET()` calls against queues.

Close method call
  Objects can now be explicitly closed. In previous releases this was done via the object destructor, and thus couldn't be error checked. Implicit closing is still preferred, but CloseOptions can be given to the constructor to control how the object is closed.

  This is particularly useful for creating permanent dynamic queues (which can accept persistent messages) which are purged and deleted upon close.

## MQSeries core module

Null-valued macros properly supported
  There are several macros, such as MQCI_NONE, which are a fixed length string of null characters. These were not properly defined in the constants.c file, and thus couldn't be used as expected.

  Now, these macros all evaluate to a string of nulls of the correct length, this you can use them precisely as documented in the MQI docs.

MQParseEvent, MQCommandRequestPCF, MQCommandResponsePCF and MQParseDeadLetter
  These core module subroutines were removed.

  MQParseDeadLetter never worked, and it will be implemented (eventually) in the same way that MQSeries::Message::RulesFormat was done, with its own XS source file.

  The other 3 all dealt with very specific implementations of the PCF format, and these were replaced by the MQSeries::Message::PCF class, which provides very generic PCF parsing and encoding routines (MQEncodePCF and MQDecodePCF).

  Mapping the generic PCF into message format specific data is done by ``private'' class methods _TranslatePCF in each of the relevant OO modules.

  This was a key prerequisite for developing MQSeries::PubSub::AdminMessage, which is also based on a PCF message format. Future implementations of special formats based on PCF should be easy. Of course, now IBM wants to move to XML for everything, so...

MQReasonToStrings
  This subroutine's implementation was dramatically reworked.

  This used to be implemented in C, inside the XS routine, but now the hash of key/value pairs mapping a numeric ReasonCode to a readable test string is done via a pair of automatically compiled files (MQSeries/Constants/Reason*.pl)

  In fact, all of the files in MQSeries/Constants are auto-generated from templates in src/pre.in, by the tool src/util/flatten_macros. This is a huge win, as it basically does the macro-to-value mapping such that the perl API is dealing with raw numbers.

  There is a non-trivial startup cost otherwise, as each and every macro has to be looked up in the symbol table, the AUTOLOAD function called, a C subroutine called, etc. This saves a few seconds of startup time.

XS code streamlined
  Most of the non-MQI subroutines were removed entirely, or moved elsewhere. The MQSeries.xs.in directory is much more lean.

XS code no longer leaks memory
  The author now fully understands the XS concepts of mortality and reference counts, and the code returns correctly mortalized, and properly reference counted values.

Support for "default" queue manager
  The QueueManager key is no longer required by most of the OO API constructors. If you have configured a default queue manager for your environment, then you can use it with the OO API as of this release. Before, the QueueManager key was required to have a true value, and since the default queue manager is ``'', and ``'' is false...

## Installation Procedures, and other Miscellany

1. 004 required, not 5.005 The 5.005 prerequisite was relaxed to 5.004, and the requirement that the perl interpreter itself be linked directly with -lthread (or -lpthread, or whatever) was removed. The MQSeries.so libraries are themselves compiled with the appropriate dependencies on libthread, and this code now works fine with a standard, out-of-the-tarball compile of perl5.004 or later.

   New CONFIG parameters
     It is now possible to explicitly disable either the server or client API compile. The Makefile.PL now does a more generic job of determining whether or not you appear to have support for the server API, which is the more common case (eg. Linux, SunOS and IRIX only have client implementations available).

     At least one site didn't support clients at all, and they didn't want to build in the support, so they can now turn it off via CONFIG.

   MANIFEST and .exclude auto-generated
     These files are now auto-generated by development utilities in the util subdirectory, rather than being updated manually.

# Changes for 1.05

This release required 5.005, built with thread support (this restriction was subsequently removed in 1.06).

## Installation Procedures

MQServer::MQSeries made optional
  Compilation of the MQServer::MQSeries API is automatically disabled on SunOS 4.1.3 and IRIX hosts, for which we do not have a server API.

constants.c.PL added
  The huge, growing list of MQSeries C macros are now extracted from the MQSeries C include files automatically, and the `@EXPORT` list is built dynamically. The code for constants.c is also auto-generated, and the code handles several different types of constant (hex, string, character, etc).

  The code also parses all of the available C header files, and makes all possible macros available. This makes maintenance of the macro list easy, but it does result in significant bloat of the namespace exported by MQSeries. So be it.

Test suite
  The test suite was reorganized to a SysV-style rc.d directory syntax, with files named 10foo.t, 20bar.t, etc.

## MQSeries

Distribution List Support
  Support for Distribution lists was added to the core MQI functions, such as MQOPEN, MQPUT and MQPUT1. This required a significant re-architecture of these functions. The OO API classes were also extended to support dist lists as well.

  This functionality is all enabled only if one compiles with V5, of course.

## MQSeries::QueueManager

MQCONN retry logic
  The MQCONN retry logic is disabled by default.

## MQSeries::Queue

MQOPEN retry logic
  This was stripped out of the code entirely, since it never really worked, and I doubt it ever would have. Bad idea.

AutoResize logic
  Logic was added to adjust the buffer size automatically, and retry an `MQGET()` call, when a truncated message is received, and truncated messages are not accepted. This functionality is available in the C++ API, the source of inspiration for the idea.

## MQSeries::Command

Documentation
  This module was finally documented, but only the object constructor and basic methods were documented. Complete documentation of the command syntax was not added until 1.06.

# Changes for 1.04

## MQSeries

Supports explicit loading of MQClient::MQSeries or MQServer::MQSeries, rather than implicit only.

## MQSeries::Command

Introduce the Command Server API, for both PCF and MQSC command messages.

## MQSeries::Message::Storable

Uses nfreeze, which is supposed to use network byte order, rather than freeze.

# Changes for 1.03

OO API
  First implementation of the OO portion of the API

XS source
  Eliminated the dual XS file templates, using one source for both V2 and V5

MQSeries core
  Added two new utility functions to the core API:

          MQParseEvent
          MQReasonToText

Locale hacks
  MQSeries.pm will automagically set reasonable values for the LANG and NLSPATH environment variables, if not set.

Documentation
  Significantly expanded documentation

# Changes for 1.02

Introduced the extended test suite
Dual client/server support
  Introduced the dual namespaces to make client vs. server usage transparent. That is, MQSeries.pm really pulls in MQServer/MQSeries.pm on a queue manager, and MQClient/MQSeries.pm otherwise.

PLMQ -> MQSeries
  Change the module name from PLMQ to MQSeries, and changed the API calls from GET to MQGET, etc., making the function mapping one to one.

typemap.PL
  Automated the typemap generation using a typemap.PL file