# $Header: dgDatabases.pl 15-aug-2006.11:23:43 sjconnol Exp $
#
# Copyright (c) 2002, 2006, Oracle. All rights reserved.
#
# NAME
# dgDatabases.pl
#
# DESCRIPTION
# This metric test determines metric information for a Data Guard configuration. For each database in the configuration, this test determines the Data Not Received, Data Not Applied, and Status.
#
# OUTPUT:
# For 9.2:
# DB Object Name, Data Not Received (logs), Data Not Applied (logs), Status
#
# For 10.1:
# DB Object Name, Data Not Received (logs), Data Not Received (MB),
# Data Not Applied (logs), Data Not Applied (MB), Status
#
# For 10.2:
# DB Object Name, Failover Time (secs), LAG Time (secs), Apply Rate (KB/sec)
# Potential Data Loss (secs), Status
#
# NOTES
# DBI handles automatic error checking.
#
# MODIFIED (MM/DD/YY)
# sjconnol 08/15/06 - 11g support
# ngade 05/09/06 - fix bug 5226727
# ngade 05/09/06 - fix bug 5203762
# ngade 04/11/06 - fix bug 5082046 for 9i db
# gallison 08/12/05 - Fix bug 4547507
# sjconnol 06/24/05 - Move get_dg_dbres_status to dgutil.pl
# gallison 09/22/04 - 10.2 support
# gallison 06/01/04 - Fix bug 3653330
# gallison 05/14/04 - Support for non-broker metrics
# gallison 03/12/04 - Fix bug 3361521
# gallison 10/13/03 - Fix version
# pbantis 06/25/03 - Handle login role
# gallison 06/04/03 - Use stdinvars
# pbantis 12/04/02 - Trace errors by RaiseError
# pbantis 11/19/02 - Show size in megabytes
# pbantis 11/12/02 - pbantis_update021101
# pbantis 11/01/02 - 10g support
# pbantis 09/26/02 - Target version support
# pbantis 07/15/02 - Exit if metric not applicable
# xxu 06/24/02 - remove /usr/local/bin/perl
# pbantis 06/06/02 - Data Not Applied = Received - Applied.
# pbantis 05/16/02 - Handle 10g dbs.
# gallison 04/29/02 - gallison_dgm
# pbantis 03/14/02 - Creation
#
use strict;
use DBI;
use DBI qw(:sql_types);
require "$ENV{EMDROOT}/sysman/admin/scripts/emd_common.pl";
require "$ENV{EMDROOT}/sysman/admin/scripts/db/dg/dgutil.pl";
# RaiseError
$SIG{__DIE__} = \&handleError;
# PrintError
$SIG{__WARN__} = \&handleWarning;
# Trace the target name.
EMD_PERL_DEBUG("Database target=$ENV{EM_TARGET_NAME}");
my $db_version = $ENV{VersionCategory};
verify_dbversion_92($db_version);
# Connect to the instance.
my %stdinArgs = get_stdinvars();
my $username = $stdinArgs{EM_TARGET_USERNAME};
my $password = $stdinArgs{EM_TARGET_PASSWORD};
my $role = $ENV{EM_TARGET_ROLE};
my $mode = 0;
if($role =~ /SYSDBA/i)
{
$mode = 2;
}
elsif($role =~ /SYSOPER/i)
{
$mode = 4;
}
my $address = $ENV{EM_TARGET_ADDRESS};
my $lda = DBI->connect('dbi:Oracle:', "$username@".$address, "$password", {ora_session_mode => $mode, PrintError => 0, RaiseError => 1});
# Register this test once we're connected.
register_metric_call($lda);
# Make a few more checks before continuing.
verifyPrimary($lda);
my $broker = verifyBroker($lda);
# evaluate metric for broker or non-broker cases (non-broker 10.1 and up)
if($broker)
{
doEval($lda, $db_version);
}
elsif($db_version !~ /9iR2/i)
{
getStatusNoBroker($lda, $db_version, 1);
}
$lda->disconnect;
exit 0;
# Parameters
# lda - The login identifier (Login Data Area).
# db_version - The database version 9iR2 or 10gR1.
sub doEval
{
my ($lda, $db_version) = @_;
# Retrieve the configuration object content.
my $indoc = "";
my $drc_obj = get_dg_document($lda, $indoc);
# Retrieve the list of sites.
my (@site_list);
my ($site_id, $site_obj);
my $drc_start_pos = -1;
my $i = 0;
while (($site_id = get_dg_token($drc_obj, "site_id", $drc_start_pos)) ne "")
{
EMD_PERL_DEBUG("site_id=$site_id");
# Retrieve the site object content.
$indoc = "";
$site_obj = get_dg_document($lda, $indoc);
$site_list[$i] = $site_obj;
$i++;
}
# Process the primary site first.
my $default_state;
my $site_start_pos;
my $potential_data_loss;
my $current_log = 0;
EMD_PERL_DEBUG("Process the primary...");
foreach $site_obj (@site_list)
{
# Parse out the default state (to determine if PRIMARY or STANDBY).
$site_start_pos = -1;
$default_state = get_dg_token($site_obj, "default_state", $site_start_pos);
if ($default_state eq "PRIMARY")
{
processSiteObject($lda, $db_version, $site_obj, $default_state, $potential_data_loss, $current_log);
last; # break out of the for loop
}
else
{
next;
}
} # foreach site
# Process the standbys.
EMD_PERL_DEBUG("Process the standbys...");
foreach $site_obj (@site_list)
{
# Parse out the default state (to determine if PRIMARY or STANDBY).
$site_start_pos = -1;
$default_state = get_dg_token($site_obj, "default_state", $site_start_pos);
if ($default_state eq "STANDBY")
{
processSiteObject($lda, $db_version, $site_obj, $default_state, $potential_data_loss, $current_log);
}
else
{
next;
}
} # foreach site
}
# Process a site object.
# Parameters
# lda - The login identifier (Login Data Area).
# db_version - The database version 9iR2 or 10g.
# site_obj - The site content object.
# default_state - The default state of the site object.
# potential_data_loss (10g) - IN/OUT- The PotentialDataLoss property value.
# current_log (9i) - IN/OUT - The primary current log.
# Return result list.
sub processSiteObject
{
my ($lda, $db_version, $site_obj, $default_state, $potential_data_loss, $current_log) = @_;
my $site_start_pos = -1;
# 9i - Parse out the site name.
my $site_name;
if ($db_version eq "9iR2")
{
$site_name = get_dg_token($site_obj, "name", $site_start_pos);
EMD_PERL_DEBUG("site_name=$site_name");
}
# Parse out the site id.
my $site_id = get_dg_token($site_obj, "site_id", $site_start_pos);
EMD_PERL_DEBUG("site_id=$site_id");
# Retrieve the site DBRESOURCE_ID property.
my $dbres_id = get_dg_property($lda, $site_id, "DBRESOURCE_ID");
EMD_PERL_DEBUG("dbres_id=$dbres_id");
# 10g - Retrieve the db resource DBDISPLAYNAME property.
my $dbres_display_name;
if (isDB10gOrHigher($db_version))
{
# Use NLS version of getdbdisplayname
$dbres_display_name = get_dbdisplayname($lda, $dbres_id);
if ($dbres_display_name eq "")
{
$dbres_display_name = get_dg_token($site_obj, "name", $site_start_pos);
}
EMD_PERL_DEBUG("dbres_display_name=$dbres_display_name");
}
# Retrieve the db resource ENABLED property.
my $dbres_enabled = get_dg_property($lda, $dbres_id, "ENABLED");
EMD_PERL_DEBUG("dbres_enabled=$dbres_enabled");
# The db resource must be enabled.
if (!($dbres_enabled =~ /YES/i))
{
EMD_PERL_DEBUG("The db resource must be enabled.");
return;
}
# Retrieve the db resource INTENDED_STATE property.
my $dbres_state = get_dg_property($lda, $dbres_id, "INTENDED_STATE");
EMD_PERL_DEBUG("dbres_state=$dbres_state");
# The db resource intended state must not be offline.
if (($dbres_state =~ /OFFLINE/i))
{
EMD_PERL_DEBUG("The db resource must not be offline.");
return;
}
# Retrieve the db resource status.
my $dbres_status = "";
my $dbres_status_text = "";
my $ignore_error = "ORA-16820";
get_dg_dbres_status($lda, $dbres_id, $dbres_status, $dbres_status_text, $ignore_error);
my $dnr_log = "";
my $dnr_size = "";
my $dna_log = "";
my $dna_size = "";
# If this is the (10gR1 or 9iR2) primary db resource...
if ($default_state eq "PRIMARY")
{
if ($db_version =~ /^10gR1/i)
{
# potential_data_loss
get10gPrimaryInfo($lda, $dbres_id, $_[4]);
}
if ($db_version =~ /^9iR2/i)
{
# current_log
get9iPrimaryInfo($lda, $dbres_id, $_[5]);
}
}
# If this is a standby db resource...
else
{
if ($db_version =~ /^10gR1/i)
{
get10gStandbyInfo($lda, $site_id, $dbres_id, $potential_data_loss, $dnr_log, $dnr_size, $dna_log, $dna_size);
}
if ($db_version =~ /^9iR2/i)
{
get9iStandbyInfo($lda, $dbres_id, $current_log, $dnr_log, $dna_log);
}
}
# Send the results back.
my $result;
if (isDB102OrHigher($db_version))
{
$result = "em_result=$dbres_display_name|$dbres_status $dbres_status_text\n";
}
elsif ($db_version =~ /^10gR1/i)
{
$result = "em_result=$dbres_display_name|$dnr_log|$dnr_size|$dna_log|$dna_size|$dbres_status $dbres_status_text\n";
}
elsif ($db_version =~ /^9iR2/i)
{
$result = "em_result=$site_name|$dnr_log|$dna_log|$dbres_status $dbres_status_text\n";
}
print $result;
EMD_PERL_DEBUG("$result");
}
# 10g - Retrieve the PotentialDataLoss property value.
# Parameters
# lda - The login identifier (Login Data Area).
# dbres_id - The db resource id.
# potential_data_loss - OUT- The PotentialDataLoss property value.
sub get10gPrimaryInfo
{
my ($lda, $dbres_id, $potential_data_loss) = @_;
# Retrieve the db resource PotentialDataLoss property.
# potential_data_loss
$_[2] = get_dg_property($lda, $dbres_id, "PotentialDataLoss");
EMD_PERL_DEBUG("potential_data_loss=$_[2]");
}
# 10g - Determine the dnr (logs), dnr (MB), dna (logs), and dna (MB).
# Parameters
# lda - The login identifier (Login Data Area).
# site_id - The site id.
# dbres_id - The db resource id.
# potential_data_loss - The PotentialDataLoss property value.
# dnr_log - OUT - Data not received (logs).
# dnr_size - OUT - Data not received (MB).
# dna_log - OUT - Data not applied (logs).
# dna_size - OUT - Data not applied (MB).
sub get10gStandbyInfo
{
my ($lda, $site_id, $dbres_id, $potential_data_loss, $dnr_log, $dnr_size, $dna_log, $dna_size) = @_;
# Calculate the data not received.
# dnr_log, dnr_size
getDataNotReceived($site_id, $potential_data_loss, $_[4], $_[5]);
# Calculate the data not applied.
# Retrieve the db resource RedoNotApplied property.
# Format: "#logs,KBs"
my $redo_not_applied = get_dg_property($lda, $dbres_id, "RedoNotApplied");
EMD_PERL_DEBUG("redo_not_applied=$redo_not_applied");
# Make sure the broker did not return any errors (ORACLE not available...)
if (($redo_not_applied =~ /ERROR/i))
{
return;
}
my @sby_logs = split(/,/, $redo_not_applied);
# Data Not Applied (logs)
# dnr_log
$_[6] = $sby_logs[0];
EMD_PERL_DEBUG("dna (logs)=$_[6]");
# Data Not Applied (MB)
# dnr_size
$_[7] = $sby_logs[1]/1024;
EMD_PERL_DEBUG("dna (MB)=$_[7]");
}
# 10g - Parse out the dnr (logs) and dnr (MB) from the PotentialDataLoss property value.
# Parameters
# site_obj - The site content object.
# potential_data_loss - The PotentialDataLoss property value.
# dnr_log - OUT - Data not received (logs).
# dnr_size - OUT - Data not received (MB).
sub getDataNotReceived
{
my ($site_id, $potential_data_loss, $dnr_log, $dnr_size) = @_;
# Format: "=#logs,KBs,=#logs,KBs,..."
my @token_list = split(/,/, $potential_data_loss);
while (my $token = shift(@token_list))
{
# =#logs
my @sub_list = split(/=/, $token);
my $standby_id = shift(@sub_list);
if ($standby_id == $site_id)
{
# Data Not Received (logs)
# dnr_log
$_[2] = shift(@sub_list);
EMD_PERL_DEBUG("dnr (logs)=$_[2]");
# Data Not Received (MB)
# dnr_size
$_[3] = shift(@token_list)/1024;
EMD_PERL_DEBUG("dnr (MB)=$_[3]");
}
else
{
# Skip over the KBs for non-matching standby.
shift(@token_list);
}
}
}
# 9i - Retrieve the current log number from the PrimaryLogSeqNumbers property.
# Parameters
# lda - The login identifier (Login Data Area).
# dbres_id - The db resource id.
# current_log - OUT- The primary current log number.
sub get9iPrimaryInfo
{
my ($lda, $dbres_id, $current_log) = @_;
# Retrieve the db resource PrimaryLogSeqNumbers property.
# Format: "current log#,last locally archived log#,standby1=last received log#,standby2=last received log#,..."
my $primary_log_seq_numbers = get_dg_property($lda, $dbres_id, "PrimaryLogSeqNumbers");
EMD_PERL_DEBUG("primary_log_seq_numbers=$primary_log_seq_numbers");
my @primary_logs = split(/,/, $primary_log_seq_numbers);
# current_log
$_[2] = $primary_logs[0];
}
# 9i - Determine the dnr (logs), and dna (logs).
# Parameters
# lda - The login identifier (Login Data Area).
# dbres_id - The db resource id.
# curent_log - The primary current log number.
# dnr_log - OUT - Data not received (logs).
# dna_log - OUT - Data not applied (logs).
sub get9iStandbyInfo
{
my ($lda, $dbres_id, $current_log, $dnr_log, $dna_log) = @_;
# Retrieve the db resource SbyLogSeqNumbers property.
# Format: "last received log#,last applied log#"
my $sby_log_seq_numbers = get_dg_property($lda, $dbres_id, "SbyLogSeqNumbers");
EMD_PERL_DEBUG("sby_log_seq_numbers=$sby_log_seq_numbers");
my @sby_logs = split(/,/, $sby_log_seq_numbers);
# Data Not Received (logs)
# dnr_log = current - received
$_[3] = $current_log - $sby_logs[0];
EMD_PERL_DEBUG("dnr (logs)=$_[3]");
# Data Not Applied (logs)
# dna_log = received - applied
$_[4] = $sby_logs[0] - $sby_logs[1];
EMD_PERL_DEBUG("dna (logs)=$_[4]");
}
sub get_dbdisplayname
{
my ($lda, $object_id) = @_;
my($indoc);
my($outdoc);
my($pos);
$indoc = "";
$outdoc = get_dg_document($lda, $indoc);
$pos = -1;
my $retstr;
## First one is value_type=
$retstr = get_dg_token($outdoc, "value", $pos);
## Second one is value=
$retstr = get_dg_token($outdoc, "value", $pos);
debug("dgcreate.get_dbdisplayname: $retstr");
return $retstr;
}