|
RSS Feed - WebSphere MQ Support
|
RSS Feed - Message Broker Support
|
 |
|
[Solved] Browsing messages in Perl. |
« View previous topic :: View next topic » |
Author |
Message
|
jgooch |
Posted: Fri May 21, 2004 7:51 am Post subject: [Solved] Browsing messages in Perl. |
|
|
 Acolyte
Joined: 29 May 2002 Posts: 63 Location: UK
|
Hi gang,
I'm trying to write a browse queue function using the Perl OO API. I can get it working using sync'd gets and a backout, but my code does not work using the MQOO_BROWSE and MQGMO_BROWSE_NEXT options. The error I receive is a 2037 (not open for input). If I change the open to use MQOO_INPUT, the script removes the messages from the queue.
Any explanation of my undoubtedly obvious ineptitude would be gratefully received.
Here's the code (apologies that the indentation has been lost):-
Quote: |
# instantiate the queue object
$o_q = MQSeries::Queue->new (
QueueManager => "MWMQDJG",
Queue => "TEST.JG",
Options => MQSeries::MQOO_BROWSE + MQSeries::MQOO_FAIL_IF_QUIESCING,
AutoOpen => 0,
) || die "Unable to instantiate MQSeries::Queue object\n";
# open the queue
unless ( $o_q->Open() ) {
die "Unable to open queue object " .
"CompCode => " . $o_q->CompCode() . " " .
"Reason => " . $o_q->Reason()."\n";
}
# set up the options for the GETting
%msg_opts = ( Options => MQSeries::MQGMO_FAIL_IF_QUIESCING +
MQSeries::MQGMO_CONVERT +
MQSeries::MQGMO_BROWSE_FIRST +
MQSeries::MQGMO_NO_WAIT,);
# get the messages
while ($message .= '') {
$o_message = MQSeries::Message->new();
# get the data from the queue
eval { $o_q->Get (
Message => $o_message,
GetMsgOpts => \%msg_opts,)
};
# check whether an error was returned from eval or if MQ completion code = -1 or 2
# suppress error reason 2033 as it is "normal" when there are no more records to process
if ($@ || $o_q->CompCode() == -1 || $o_q->CompCode() == 2 && $o_q->Reason() != 2033) {
die "Unable to get message " .
"CompCode => " . $o_q->CompCode() . " " .
"Reason => " . $o_q->Reason()."\n";
}
# MQ warning comp code = 1 treat as OK but issue warning
if ($o_q->CompCode() == 1) {
print "MQ warning issued ".
"CompCode => ".$o_q->CompCode()." Reason => ".$o_q->Reason()."\n";
}
$message = $o_message->Data();
if ($message .= '') {
push(@q_contents, $message);
$message_count++;
}
# set up more options for the GETting
%msg_opts = ( Options => MQSeries::MQGMO_FAIL_IF_QUIESCING +
MQSeries::MQGMO_CONVERT +
MQSeries::MQGMO_BROWSE_NEXT +
MQSeries::MQGMO_NO_WAIT,);
}
print "$message_count message(s) read\n";
|
J. |
|
Back to top |
|
 |
bduncan |
Posted: Fri May 21, 2004 9:39 am Post subject: |
|
|
Padawan
Joined: 11 Apr 2001 Posts: 1554 Location: Silicon Valley
|
Hmm... It's been about two years since I worked with the Perl API, but I recall having trouble with browse myself. I believe I had to add some additional options to the MQOPEN call to get it to work.
Perhaps you had to specify both browse and input?
MQSeries::MQOO_BROWSE + MQSeries::MQOO_INPUT
??
There's this section from the programming guide:
Quote: |
Removing a message you have browsed
You can remove from the queue a message you have already browsed provided you have opened the queue for removing messages as well as for browsing. (You must specify one of the MQOO_INPUT_* options, as well as the MQOO_BROWSE option, on your MQOPEN call.)
To remove the message, call MQGET again, but in the Options field of the MQGMO structure, specify MQGMO_MSG_UNDER_CURSOR. In this case, the MQGET call ignores the MsgId, CorrelId, and GroupId fields of the MQMD structure.
In the time between your browsing and removal steps, another program may have removed messages from the queue, including the message under your browse cursor. In this case, your MQGET call returns a reason code to say that the message is not available.
|
So perhaps the Perl API is a little squirrely in that it requires you to specify both even if you don't plan on removing messages that you browse...
Amazing how fast things go when you aren't doing them everyday  _________________ Brandon Duncan
IBM Certified MQSeries Specialist
MQSeries.net forum moderator |
|
Back to top |
|
 |
clindsey |
Posted: Fri May 21, 2004 10:58 am Post subject: |
|
|
Knight
Joined: 12 Jul 2002 Posts: 586 Location: Dallas, Tx
|
I ran mqtrace to see what your open options and get options were and the trace went from MQOpen to MQClose. I had to change "while ($message .= '') {" to get into drop into the get loop. This could be just my level of perl though.
The trace also showed that the open with MQOO_BROWSE was ok, but the GMO options were not getting picked up.
With the following changes, it started working for me:
Code: |
# set up the options for the GETting
#%msg_opts = ( Options => MQSeries::MQGMO_FAIL_IF_QUIESCING +
#MQSeries::MQGMO_CONVERT +
#MQSeries::MQGMO_BROWSE_FIRST +
#MQSeries::MQGMO_NO_WAIT,);
my $GetMsgOpts = { Options => MQGMO_FAIL_IF_QUIESCING | MQGMO_NO_WAIT | MQGMO_BROWSE_NEXT,
MatchOptions => MQMO_NONE, };
eval { $o_q->Get (
Message => $o_message,
GetMsgOpts => $GetMsgOpts,)
};
# set up more options for the GETting
#%msg_opts = ( Options => MQSeries::MQGMO_FAIL_IF_QUIESCING +
#MQSeries::MQGMO_CONVERT +
#MQSeries::MQGMO_BROWSE_NEXT +
#MQSeries::MQGMO_NO_WAIT,);
|
Without setting MatchOptions to none, you have to reset msgid and correlid after each get or you won't match. It's easier to just override the default match options.
Hope this helps,
Charlie |
|
Back to top |
|
 |
any2xml |
Posted: Sat May 22, 2004 6:53 pm Post subject: Web-based MQ monitor using MQSeries module |
|
|
Apprentice
Joined: 18 May 2004 Posts: 42
|
I am interested in developing a web-based monitor for MQ using the MQSeries module. Looks like you folks have gone along that path a little. Is it possible to link with you so we can all contribute a little and come up with a generalized monitor? _________________ A Perl Hacker
http://www.goreliance.com
http://www.any2xml.com |
|
Back to top |
|
 |
bduncan |
Posted: Sun May 23, 2004 9:08 am Post subject: |
|
|
Padawan
Joined: 11 Apr 2001 Posts: 1554 Location: Silicon Valley
|
I wrote such a tool (although it wasn't web based, but could easily be made so) called heartbeat.pl that appeared in the MQUpdate journal a year or two ago... _________________ Brandon Duncan
IBM Certified MQSeries Specialist
MQSeries.net forum moderator |
|
Back to top |
|
 |
jgooch |
Posted: Mon May 24, 2004 7:00 am Post subject: |
|
|
 Acolyte
Joined: 29 May 2002 Posts: 63 Location: UK
|
Guys,
Thanks for the help. I've now got it working, using Charlie's settings. You don't need to add MQOO_INPUT_SHARED to the queue open unless you're going to remove the messages once browsed.
I've also got this working where the browsing is limited to a given correlId (which are used at our site to identify batches of messages). The function also sets MQGMO_BROWSE_FIRST for the first iteration of the loop, before changing the option to use MQGMO_BROWSE_NEXT, so that each call to the function starts at the top of the queue (rather than wherever the cursor was when the last call finished).
For reference, here's the function code. We also have an "openq" function, that accepts MQOO_BROWSE and from which is returned a queue object that must be passed into "browseq"
Quote: |
sub browseq {
# ---------------------------------------------------------------
# Subroutine : browseq
# Function : Browses the contents of a queue, returns an array.
# : If correl_id is provided, only matching messages are returned.
# Calling syntax : &browseq($o_q, $log_file, $correl_id);
# ---------------------------------------------------------------
my ($o_q, $log_file, $correl_id) = @_;
my $o_message;
my $message = 'start';
my $message_count = 0;
my @q_contents;
my %msg_desc;
my %msg_opts;
# check parameters
if ($#_ > 2) {
return ($STD::PARAMERROR, "browseq: Usage : browseq(queue_object, log_file, correl_id);");
}
if ($correl_id) {
%msg_opts = ( Options => MQSeries::MQGMO_FAIL_IF_QUIESCING |
MQSeries::MQGMO_NO_WAIT |
MQSeries::MQGMO_BROWSE_FIRST,
MatchOptions => MQSeries::MQMO_MATCH_CORREL_ID, );
%msg_desc = ( CorrelId => $correl_id,
MsgId => MQSeries::MQMI_NONE );
}
else {
%msg_opts = ( Options => MQSeries::MQGMO_FAIL_IF_QUIESCING |
MQSeries::MQGMO_NO_WAIT |
MQSeries::MQGMO_BROWSE_FIRST,
MatchOptions => MQSeries::MQMO_NONE, );
}
# get the messages
while ($message .= '') {
$o_message = MQSeries::Message->new(
MsgDesc => \%msg_desc );
# get the data from the queue
eval { $o_q->Get (
Message => $o_message,
GetMsgOpts => \%msg_opts,)
};
# check whether an error was returned from eval or if MQ completion code = -1 or 2
# suppress error reason 2033 as it is "normal" when there are no more records to process
if ($@ || $o_q->CompCode() == -1 || $o_q->CompCode() == 2 && $o_q->Reason() != 2033) {
return ($STD::MQERROR,
"browseq: Unable to get message " .
"CompCode => " . $o_q->CompCode() . " " .
"Reason => " . $o_q->Reason(), $log_file);
}
# MQ warning comp code = 1 treat as OK but issue warning to log file
if ($o_q->CompCode() == 1) {
&writelog($STD::WARNING,
"browseq: MQ warning issued ".
"CompCode => ".$o_q->CompCode()." Reason => ".$o_q->Reason(),
$log_file);
}
$message = $o_message->Data();
if ($message .= '') {
push(@q_contents, $message);
$message_count++;
}
if ($correl_id) {
%msg_opts = ( Options => MQSeries::MQGMO_FAIL_IF_QUIESCING |
MQSeries::MQGMO_NO_WAIT |
MQSeries::MQGMO_BROWSE_NEXT,
MatchOptions => MQSeries::MQMO_MATCH_CORREL_ID, );
%msg_desc = ( CorrelId => $correl_id,
MsgId => MQSeries::MQMI_NONE );
}
else {
%msg_opts = ( Options => MQSeries::MQGMO_FAIL_IF_QUIESCING |
MQSeries::MQGMO_NO_WAIT |
MQSeries::MQGMO_BROWSE_NEXT,
MatchOptions => MQSeries::MQMO_NONE, );
}
}
&writelog($STD::INFO, "browseq: $message_count message(s) read", $log_file);
return (0,"",@q_contents);
}
# ---------------------------------------------------------------
# - end of browseq
# --------------------------------------------------------------- |
J. |
|
Back to top |
|
 |
|
|
 |
|
Page 1 of 1 |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|
|
|