#!/usr/local/bin/perl
#
# $Header: dbAdrUtil.pl 28-sep-2007.14:33:42 jsoule Exp $
#
# dbAdrUtil.pl
#
# Copyright (c) 2006, 2008, Oracle. All rights reserved.  
#
#    NAME
#      dbAdrUtil.pl - database ADR utilities
#
#    DESCRIPTION
#      Utilities for accessing ADR for database
#
#    NOTES
#      <other useful comments, qualifications, etc.>
#
#    MODIFIED   (MM/DD/YY)
#       dchakumk 03/10/08 - XbranchMerge dchakumk_6752_xbmsrc from
#                           st_emdbsa_11.1
#       jsoule   09/28/07 - add ASM sid routine
#       loliu    02/19/07 - Creation


require "emd_common.pl";

use strict;
use DBI;

# Return the value for a given key in the v$diag_info table for
# the database diagnostic framework
sub get_diag_info_from_db
{
  # the key for which to look up information from v$diag_info
  my ($param_key) = @_; 
  
  my $param_value = undef;

  # For TESTING: comment out stdin args
  my %stdinArgs = get_stdinvars();
  my $username = $stdinArgs{"EM_TARGET_USERNAME"};
  my $password = $stdinArgs{"EM_TARGET_PASSWORD"};
  my $address = $ENV{EM_TARGET_ADDRESS};
  my $role = $ENV{EM_TARGET_ROLE};

  # For TESTING: un-comment for manual testing and fill in the values
  # my $username = "";
  # my $password = "";
  # my $address = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=)(PORT=))(CONNECT_DATA=(SID=)))";
  # my $role = "";

  my $mode = 0;

  if($role =~ /SYSDBA/i)
  {
      $mode = 2;
  }
  elsif($role =~ /SYSOPER/i)
  {
      $mode = 4;
  }

  # --------------------------------------------------------------------
  # +++ Establish Target DB Connection
  # --------------------------------------------------------------------

  my $dbh = DBI->connect('dbi:Oracle:', "$username@".$address, "$password", 
      {ora_session_mode => $mode, PrintError => 0, RaiseError => 0, AutoCommit => 0});
  if (!$dbh)
  {
    EMD_PERL_WARN("get_diag_info_from_db: Could not connect to $username/$address: $DBI::errstr");
    return $param_value;
  }

  register_metric_call($dbh);

  # Since v$diag_info contains information for the database instance we
  # are connecting to, we don't need to select on INST_ID, which is needed
  # if we were joining gv$diag_info and v$instance
  my $sql = "select VALUE from v\$diag_info where NAME=?";

  my $sth = $dbh->prepare($sql);

  if (!$sth)
  {
    EMD_PERL_WARN("get_diag_info_from_db: prepare($sql) failed: $DBI::errstr");
    return $param_value;
  }

  my $rc = $sth->execute($param_key);
  if (!$rc)
  {
    EMD_PERL_WARN("get_diag_info_from_db: execute($param_key) failed: $DBI::errstr");
    return $param_value;
  }

  my @fetched_rows;
  @fetched_rows = $sth->fetchrow_array();

  if (@fetched_rows != 1)
  {
    EMD_PERL_WARN("get_diag_info_from_db: @fetched_rows rows are returned");
  }
  $param_value = $fetched_rows[0];

  EMD_PERL_DEBUG("get_diag_info_from_db: diag_info $param_key=$param_value");
  $sth->finish();
  $dbh->disconnect;
  return $param_value;
}

#
# Function: get_asm_sid_from_db
#
# Return:   the value for the instance name of the ASM for which this database
#           is an asm_client -- (empty string for 'not a client')
#
sub get_asm_sid_from_db
{
  my $asm_sid = "";

  my %stdinArgs = get_stdinvars();
  my $username  = $stdinArgs{"EM_TARGET_USERNAME"};
  my $password  = $stdinArgs{"EM_TARGET_PASSWORD"};
  my $address   = $ENV{EM_TARGET_ADDRESS};
  my $role      = $ENV{EM_TARGET_ROLE};

  my $mode = 0;

  if ($role =~ /SYSDBA/i)
  {
    $mode = 2;
  }
  elsif ($role =~ /SYSOPER/i)
  {
    $mode = 4;
  }

  # --------------------------------------------------------------------
  # +++ Establish Target DB Connection
  # --------------------------------------------------------------------

  my $dbh = DBI->connect('dbi:Oracle:',
                         "$username@".$address,
                         "$password", 
                         { ora_session_mode => $mode,
                           PrintError       => 0,
                           RaiseError       => 0,
                           AutoCommit       => 0});
  if (!$dbh)
  {
    EMD_PERL_WARN("get_asm_sid_from_db: ".
                  "Could not connect to $username/$address: ".
                  $DBI::errstr);
    return $asm_sid;
  }

  register_metric_call($dbh);

  # (We don't have to deal with empty v$asm_client view specially.)
  my $sql = "select instance_name from v\$asm_client where rownum <= 1";

  my $sth = $dbh->prepare($sql);
  if ($sth)
  {
    my $rc = $sth->execute;
    if ($rc)
    {
      my @fetched_row;
      @fetched_row = $sth->fetchrow_array();

      if (@fetched_row > 0)
      {
        $asm_sid = $fetched_row[0];
      }
      elsif ($sth->err)
      {
        EMD_PERL_WARN("get_asm_sid_from_db: ".
                      "fetch failed: ".
                      $DBI::errstr);
      }
    }
    else
    {
      EMD_PERL_WARN("get_asm_sid_from_db: ".
                    "execute failed: ".
                    $DBI::errstr);
    }
  }
  else
  {
    EMD_PERL_WARN("get_asm_sid_from_db: ".
                  "prepare($sql) failed: ".
                  $DBI::errstr);
  }

  EMD_PERL_DEBUG("get_asm_sid_from_db: asm_client instance_name=$asm_sid");
  $sth->finish();
  $dbh->disconnect;
  return $asm_sid;
}

# Return the name of the state file using the given suffix
sub get_state_file_name
{
  my ($suffix) = @_;

  my $target_guid = $ENV{EM_TARGET_GUID};
  my $state_root = $ENV{EM_AGENT_STATE_DIR};

  # build the fully qualify state file path
  my $separator = $^O =~ m/MSWin32/ ? "\\" : "\/";

  # location of the state file is
  #  $EMDROOT/sysman/emd/state/adr/<TARGET_GUID>.<suffix>
  my $adrStateDir = $state_root.$separator."sysman".$separator."emd".$separator."state".$separator."adr";

  # create ADR state directory if directory does not exist
  # OK to "die" here since the user needs to fix the file permission
  if (!(-e $adrStateDir))
  {
    mkdir $adrStateDir or die "em_error=Cannot create $adrStateDir";
  }

  my $state_file = $adrStateDir.$separator."$target_guid.$suffix";
  EMD_PERL_DEBUG("get_state_file_name: $state_file");
  return $state_file;

}

# If the state value is defined, save it in a state file using the given
# file name suffix. Otherwise, read the previous state value from the state
# file and return it.
#
# Arguments: $_[0] - the state to save
#            $_[1] - the file name suffix
#            $_[2] - (optional) flag to indicate state is not a directory
#                               default value is false (is a directory)
sub read_or_save_state
{
  my ($state, $suffix, $nondir) = @_;
  my $state_file = get_state_file_name($suffix);
  
  my $new_state = $state;

  # save state if defined
  if (($nondir && $state) || -d $state)
  {
    # open state file and write out the state
    if (open (STATE, "+> $state_file"))
    {
      print STATE "$state\n";
      close STATE;
      EMAGENT_PERL_DEBUG("saved $state to $state_file");
    }
  }
  # read state from state file
  else
  {
    if (open(STATE, "< $state_file"))
    {
      while (<STATE>)
      {
        chomp;
        $new_state = $_;
      }
      close STATE;
      EMAGENT_PERL_DEBUG("read \'$new_state\' from $state_file");
    }
  }
  return $new_state;
}

1;
