MINI MINI MANI MO
#
# $Header: rdbms/src/client/tools/asmcmd/modules/asmcmdfgrp.pm /main/8 2016/09/23 20:19:03 diguzman Exp $
#
# asmcmdfgrp.pm
#
# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
#
# NAME
# asmcmdfgrp - ASM CoMmanD line interface for File GRouP operations
#
# DESCRIPTION
# This module contains the interface for ASMCMD/ASM filegroup-related and
# operations, such as creation, removing and listing the contents of
# V$ASM_FILEGROUP.
#
# NOTES
# <other useful comments, qualifications, etc.>
#
# MODIFIED (MM/DD/YY)
# diguzman 09/20/16 - 21270117: implement move file to file group command
# diguzman 06/29/16 - 23584826: lsfg display used quota
# diguzman 05/30/16 - 19654070: Little change at _no_instance_cmd routine
# diguzman 05/10/16 - 23232867: Convert to string only client type field
# diguzman 04/12/16 - 22855558: lsfg diplay names instead of numbers
# diguzman 02/02/16 - 21204059: fix output of lsfg w/ -G & --filegorup
# bhshanmu 07/27/15 - bhshanmu_perl_522_changes_for_rdbms
# diguzman 11/12/14 - Creation
#
############################ Functions List #################################
#
# init
# is_asmcmd
# asmcmdfgrp_chfg_char
# asmcmdfgrp_chfg_end
# asmcmdfgrp_chfg_start
# asmcmdfgrp_get_asmcmd_cmds
# asmcmdfgrp_get_cmd_desc
# asmcmdfgrp_get_cmd_syntax
# asmcmdfgrp_is_cmd
# asmcmdfgrp_is_no_instance_cmd
# asmcmdfgrp_is_wildcard_cmd
# asmcmdfgrp_mkfg_char
# asmcmdfgrp_mkfg_end
# asmcmdfgrp_mkfg_start
# asmcmdfgrp_parse_int_args
# asmcmdfgrp_process_chfg
# asmcmdfgrp_process_cmd
# asmcmdfgrp_process_help
# asmcmdfgrp_process_lsfg
# asmcmdfgrp_process_mkfg
# asmcmdfgrp_process_rmfg
# asmcmdfgrp_process_mvfile
# asmcmdfgrp_syntax_error
#
#############################################################################
package asmcmdfgrp;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(asmcmdfgrp_init
%asmcmdfgrp_cmds);
use strict;
use DBI qw(:sql_types);
use Getopt::Long qw(:config no_ignore_case bundling);
use Data::Dumper;
use asmcmdglobal;
use asmcmdshare;
use asmcmdparser;
use XML::Parser;
use asmcmdexceptions;
use asmcmdxmlexceptions;
use List::Util qw[min max];
######################### ASMCMDFGRP Global Constants #########################
# ASMCMD Column Header Names:
# Below are the names of the column headers for lsfg.
our (%asmcmdfgrp_lsfg_header) = (
'file_group' , 'File Group' ,
'disk_group' , 'Disk Group' ,
'quota_group', 'Quota Group',
'used_quota_mb', 'Used Quota MB',
'client_type', 'Client Type',
'client_name', 'Client Name',
'property', 'Property',
'value', 'Value',
'file_type', 'File Type'
);
######################### ASMCMDFGRP Global Variables #########################
our (%asmcmdfgrp_cmds) = ('mkfg' => {},
'rmfg' => {},
'chfg' => {},
'lsfg' => {},
'mvfile' => {});
our ($fgstmt) = 'dummy';
our ($xml_error) = 'dummy';
our (@asmcmdfgrp_parser_state) = ('dummy');
our (@asmcmdfgrp_parser_fgrp) = ('dummy');
our (@asmcmdfgrp_parser_ppty) = ('dummy');
our ($asmcmdfgrp_parser_text) = ('dummy') ; # to parse for invalid text
our (@asmcmdfgrp_parser_quorum);
sub is_asmcmd
{
return 1;
}
########
# NAME
# asmcmdfgrp_init
#
# DESCRIPTION
# This function initializes the asmcmdfgrp module. For now it simply
# registers its callbacks with the asmcmdglobal module.
#
# PARAMETERS
# None
#
# RETURNS
# Null
#
# NOTES
# Only asmcmdcore_main() calls this routine.
########
sub init
{
# All of the arrays defined in the asmcmdglobal module must be
# initialized here. Otherwise, an internal error will result.
push (@asmcmdglobal_command_callbacks, \&asmcmdfgrp_process_cmd);
push (@asmcmdglobal_help_callbacks, \&asmcmdfgrp_process_help);
push (@asmcmdglobal_command_list_callbacks, \&asmcmdfgrp_get_asmcmd_cmds);
push (@asmcmdglobal_is_command_callbacks, \&asmcmdfgrp_is_cmd);
push (@asmcmdglobal_is_wildcard_callbacks, \&asmcmdfgrp_is_wildcard_cmd);
push (@asmcmdglobal_syntax_error_callbacks, \&asmcmdfgrp_syntax_error);
push (@asmcmdglobal_no_instance_callbacks, \&asmcmdfgrp_is_no_instance_cmd);
%asmcmdglobal_cmds = (%asmcmdglobal_cmds, %asmcmdfgrp_cmds);
#Perform ASMCMD consistency check if enabled
if ($asmcmdglobal_hash{'consistchk'} eq 'y')
{
if (!asmcmdshare_check_option_consistency(%asmcmdfgrp_cmds))
{
exit 1;
}
}
}
########
# NAME
# asmcmdfgrp_process_cmd
#
# DESCRIPTION
# This routine calls the appropriate routine to process the command
# specified by $asmcmdglobal_hash{'cmd'}.
#
# PARAMETERS
# dbh (IN) - initialized database handle, must be non-null.
#
# RETURNS
# 1 if command is found in the asmcmdfgrp module; 0 if not.
#
# NOTES
# Only asmcmdcore_shell() calls this routine.
########
sub asmcmdfgrp_process_cmd
{
my ($dbh) = @_;
my ($succ) = 0;
# Get current command from global value, which is set by
# asmcmdfgrp_parse_asmcmd_args()and by asmcmdcore_shell().
my ($cmd) = $asmcmdglobal_hash{'cmd'};
# Declare and initialize hash of function pointers, each designating a
# routine that processes an ASMCMDfgrp command.
my (%cmdhash) = (mkfg => \&asmcmdfgrp_process_mkfg,
rmfg => \&asmcmdfgrp_process_rmfg,
chfg => \&asmcmdfgrp_process_chfg,
lsfg => \&asmcmdfgrp_process_lsfg,
mvfile => \&asmcmdfgrp_process_mvfile);
if (defined ( $cmdhash{ $cmd } ))
{
# If user specifies a known command, then call routine to process it. #
$cmdhash{ $cmd }->($dbh);
$succ = 1;
}
return $succ;
}
########
# NAME
# asmcmdfgrp_mkfg_start
#
# DESCRIPTION
# This function processes the start of xml tags in mkfg.
#
# PARAMETERS
# expat (IN) - expat parser object
# element (IN) - tag element name
# attrs (IN) - tag element attributes
#
# RETURNS
# Null.
#
# NOTES
# Only asmcmdfgrp_process_mkfg() calls this function.
########
sub asmcmdfgrp_mkfg_start
{
my ($expat, $element, %ppty) = @_;
my (@eargs);
my ($name); # file group NAME
my ($dgnam); # Disk Group NAMe
my ($cttyp); # ClienT TYPe
my ($ctnam); # ClienT NAMe
my ($fltyp); # FiLe TYPe
if ($element eq 'filegroup')
{
if (@asmcmdfgrp_parser_state != 0)
{
asmcmdshare_error_msg(9391, undef);
$xml_error = 1;
return;
}
push (@asmcmdfgrp_parser_state, $element);
if (defined($ppty{'name'}))
{
$name = uc $ppty{'name'};
}
else
{
asmcmdshare_error_msg(9391, undef);
$xml_error = 1;
return;
}
if (defined($ppty{'dg'}))
{
$dgnam = uc $ppty{'dg'};
}
else
{
asmcmdshare_error_msg(9391, undef);
$xml_error = 1;
return;
}
if (defined($ppty{'client_type'}))
{
$cttyp = uc $ppty{'client_type'};
# Only these three client types are supported
unless ($cttyp eq 'DATABASE' || $cttyp eq 'CLUSTER' || $cttyp eq 'VOLUME')
{
asmcmdshare_error_msg(9391, undef);
$xml_error = 1;
return;
}
}
else
{
asmcmdshare_error_msg(9391, undef);
$xml_error = 1;
return;
}
if (defined($ppty{'client_name'}))
{
$ctnam = uc $ppty{'client_name'};
}
else
{
asmcmdshare_error_msg(9391, undef);
$xml_error = 1;
return;
}
$fgstmt = "ALTER DISKGROUP $dgnam ADD FILEGROUP $name $cttyp $ctnam ";
@asmcmdfgrp_parser_fgrp = ();
@asmcmdfgrp_parser_ppty = ();
}
elsif ($element eq 'p')
{
my ($string, $name, $value, $clause);
if (!defined($asmcmdfgrp_parser_state[$#asmcmdfgrp_parser_state]) ||
$asmcmdfgrp_parser_state[$#asmcmdfgrp_parser_state] ne 'filegroup')
{
asmcmdshare_error_msg(9391, undef);
$xml_error = 1;
return;
}
push (@asmcmdfgrp_parser_state, $element);
if (defined ($ppty{'name'}))
{
$name = $ppty{'name'};
}
if (defined ($ppty{'value'}))
{
$value = $ppty{'value'};
}
if (defined ($ppty{'file_type'}))
{
$fltyp = $ppty{'file_type'};
}
if (defined ($fltyp))
{
$clause = qq('$fltyp.$name' = '$value');
}
else
{
$clause = qq('$name' = '$value');
}
push (@asmcmdfgrp_parser_ppty, $clause);
}
else
{
@eargs = ($element);
asmcmdshare_error_msg(9390, \@eargs);
$xml_error = 1;
return;
}
}
########
# NAME
# asmcmdfgrp_mkfg_end
#
# DESCRIPTION
# This function processes the end of xml tags in mkfg.
#
# PARAMETERS
# expat (IN) - expat parser object
# element (IN) - tag element name
#
# RETURNS
# Null.
#
# NOTES
# Only asmcmdfgrp_process_mkfg() calls this function.
########
sub asmcmdfgrp_mkfg_end
{
my ($expat, $element) = @_;
pop @asmcmdfgrp_parser_state;
if ($element eq 'filegroup')
{
if (@asmcmdfgrp_parser_ppty > 0)
{
$fgstmt .= uc "SET " . join(', ', @asmcmdfgrp_parser_ppty);
@asmcmdfgrp_parser_ppty = ();
}
}
}
########
# NAME
# asmcmdfgrp_mkfg_char
#
# DESCRIPTION
# This function processes the text value of xml node in mkfg.
#
# PARAMETERS
# expat (IN) - expat parser object
# string (IN) - one line of text from text node
#
# RETURNS
# Null.
#
# NOTES
# Only asmcmdfgrp_process_mkfg() calls this function.
########
sub asmcmdfgrp_mkfg_char
{
my ($expat, $string) = @_ ;
# in case of multi-line, this callback is called for each line,
# append and collect all lines together
if ( length (chomp($string)) > 0 )
{
$asmcmdfgrp_parser_text .= $string ;
}
}
########
# NAME
# asmcmdfgrp_process_mkfg
#
# DESCRIPTION
# This function creates a file group.
#
# PARAMETERS
# dbh (IN) - initialized database handle, must be non-null.
#
# RETURNS
# Null.
#
# NOTES
# Only asmcmdfgrp_process_cmd() calls this function.
########
sub asmcmdfgrp_process_mkfg
{
my ($dbh) = shift;
my (%args);
my ($args_ref);
my ($qry, $ret);
my ($parser, $file);
my ($string_args) = '';
my ($hdls);
my (@eargs);
$xml_error = 0;
# Get option parameters, if any.
$ret = asmcmdfgrp_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
return unless defined ($ret);
$args_ref = $args{'mkfg'};
# check for a configuration file
if ($args_ref->[0] =~ m/\.xml$/)
{
my ($rc) = asmcmdshare_xml_exists($args_ref->[0]);
return unless defined($rc);
$file = $args_ref->[0];
}
else
{
# The argument does not look like an XML file name. We'll try to parse it
# as an XML string.
$string_args = join(' ', @{$args_ref});
}
@asmcmdfgrp_parser_state = ();
$fgstmt = "";
# We do not expect any text values for any nodes.
$asmcmdfgrp_parser_text = "" ;
# specify the handler callbacks
$hdls = { Start => \&asmcmdfgrp_mkfg_start,
End => \&asmcmdfgrp_mkfg_end,
Char => \&asmcmdfgrp_mkfg_char };
$parser = XML::Parser->new(Handlers => $hdls,
ErrorContext => 5);
eval
{
if (defined($file))
{
$parser->parsefile($file);
}
else
{
$parser->parse($string_args);
}
};
if (asmcmdxmlexceptions::catch())
{
my (@msg, $err);
$err = asmcmdxmlexceptions::getErrmsg();
@msg = split(/\n/, $err);
if ($msg[$#msg] =~ m/Parser.pm/)
{
pop @msg;
}
$err = join("\n", @msg) ."\n";
@eargs = ($err);
asmcmdshare_error_msg(9395, \@eargs);
return;
}
# error out, if any of the nodes has text values. simply print the text.
$asmcmdfgrp_parser_text =~ s/\s+// ;
if (length($asmcmdfgrp_parser_text) > 0)
{
$xml_error = 1 ;
@eargs = ($asmcmdfgrp_parser_text);
asmcmdshare_error_msg(9395, \@eargs);
return ;
}
if ($xml_error == 1)
{
return;
}
# Run SQL. #
asmcmdshare_trace(3, $fgstmt, 'y', 'n');
$ret = asmcmdshare_do_stmt($dbh, $fgstmt);
}
########
# NAME
# asmcmdfgrp_process_rmfg
#
# DESCRIPTION
# This function deletes a fg.
#
# PARAMETERS
# dbh (IN) - initialized database handle, must be non-null.
#
# RETURNS
# Null.
#
# NOTES
# Only asmcmdfgrp_process_cmd() can call this routine.
########
sub asmcmdfgrp_process_rmfg
{
my ($dbh) = shift;
my (%args); # Argument hash used by getopts(). #
my (%norm); # See asmcmdshare_normalize_path() return value comments. #
my ($ret); # asmcmdfgrp_parse_int_args() return value. #
my ($path); # User-entered raw path for deletion. #
my ($qry); # SQL query statement. #
my ($cascade) = '';
my ($dg);
my ($name);
my ($mode);
# Get option parameters, if any.
$ret = asmcmdfgrp_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
return unless defined ($ret);
# TODO: Enable this option once Bug 20951338 is fixed.
# $cascade = ' CASCADE' if (defined($args{'r'}));
$dg = shift @{$args{'rmfg'}};
$name = shift @{$args{'rmfg'}};
$qry = uc "ALTER DISKGROUP $dg DROP FILEGROUP $name" . $cascade;
$ret = asmcmdshare_do_stmt($dbh, $qry);
return;
}
########
# NAME
# asmcmdfgrp_process_mvfile
#
# DESCRIPTION
#
# PARAMETERS
# dbh (IN) - initialized database handle, must be non-null.
#
# RETURNS
# Null.
#
# NOTES
# Only asmcmdfgrp_process_cmd() can call this routine.
########
sub asmcmdfgrp_process_mvfile
{
my $dbh = shift;
my $ret;
my $file;
my $gnum;
my $dgname;
my $fgname;
my $qry;
my @eargs;
my %args;
my %norm;
$ret = asmcmdfgrp_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
if (defined($args{'G'}))
{
$dgname = uc($args{'G'});
$gnum = asmcmdshare_get_gnum_from_gname($dbh, $args{'G'});
if (!defined ($gnum))
{
@eargs = ($dgname);
# ASMCMD-8001: diskgroup '%s' does not exist or is not mounted
asmcmdshare_error_msg(8001, \@eargs);
return;
}
}
if (defined($args{'filegroup'}))
{
$fgname = uc($args{'filegroup'});
unless (defined(asmcmdshare_filegroup_exists($dbh, $fgname)))
{
my (@eargs) = ($fgname);
# ASMCMD-8609: file group '%s' does not exist
asmcmdshare_error_msg(8609, \@eargs);
return;
}
}
foreach $file (@{$args{'mvfile'}})
{
my $i;
my $alias;
my @dg_nums;
my @paths;
# Replace Windows style '\\' to Unix style '\/'
$file =~ s/\\/\//g;
%norm = asmcmdshare_normalize_path($dbh, $file, 0, \$ret);
next unless ($ret == 0);
@paths = @{ $norm{'path'} };
unless (@paths > 0) # The file name should expand at least to one file
{
@eargs = (uc($file));
# ASMCMD-8014 "file '%s' does not exist"
asmcmdshare_error_msg(8014, \@eargs);
next;
}
@dg_nums = @{ $norm{'gnum'} };
for ($i = 0; $i < @paths; $i++)
{
# The specified file must exist in the specified disk group
next unless ($dg_nums[$i] == $gnum);
$alias = $paths[$i];
$qry = "ALTER DISKGROUP $dgname MOVE FILE '$alias' TO FILEGROUP $fgname";
$ret = asmcmdshare_do_stmt($dbh, $qry);
}
}
}
########
# NAME
# asmcmdfgrp_chfg_start
#
# DESCRIPTION
# This function processes the start of xml tags in chfg.
#
# PARAMETERS
# expat (IN) - expat parser object
# element (IN) - tag element name
# attrs (IN) - tag element attributes
#
# RETURNS
# Null.
#
# NOTES
# Only asmcmdfgrp_process_chfg() calls this function.
########
sub asmcmdfgrp_chfg_start
{
my ($expat, $element, %ppty) = @_;
my (@eargs);
my ($name); # file group NAME
my ($dgnam); # Disk Group NAMe
my ($cttyp); # ClienT TYPe
my ($ctnam); # ClienT NAMe
my ($fltyp); # FiLe TYPe
if ($element eq 'filegroup')
{
if (@asmcmdfgrp_parser_state != 0)
{
asmcmdshare_error_msg(9391, undef);
$xml_error = 1;
return;
}
push (@asmcmdfgrp_parser_state, $element);
if (defined($ppty{'name'}))
{
$name = uc $ppty{'name'};
}
else
{
asmcmdshare_error_msg(9391, undef);
$xml_error = 1;
return;
}
if (defined($ppty{'dg'}))
{
$dgnam = uc $ppty{'dg'};
}
else
{
asmcmdshare_error_msg(9391, undef);
$xml_error = 1;
return;
}
$fgstmt = "ALTER DISKGROUP $dgnam MODIFY FILEGROUP $name ";
@asmcmdfgrp_parser_fgrp = ();
@asmcmdfgrp_parser_ppty = ();
}
elsif ($element eq 'p')
{
my ($string, $name, $value, $clause);
if (!defined($asmcmdfgrp_parser_state[$#asmcmdfgrp_parser_state]) ||
$asmcmdfgrp_parser_state[$#asmcmdfgrp_parser_state] ne 'filegroup')
{
asmcmdshare_error_msg(9391, undef);
$xml_error = 1;
return;
}
push (@asmcmdfgrp_parser_state, $element);
if (defined ($ppty{'name'}))
{
$name = $ppty{'name'};
}
if (defined ($ppty{'value'}))
{
$value = $ppty{'value'};
}
if (defined ($ppty{'file_type'}))
{
$fltyp = $ppty{'file_type'};
}
if (defined ($fltyp))
{
$clause = qq('$fltyp.$name' = '$value');
}
else
{
$clause = qq('$name' = '$value');
}
push (@asmcmdfgrp_parser_ppty, $clause);
}
else
{
@eargs = ($element);
asmcmdshare_error_msg(9390, \@eargs);
$xml_error = 1;
return;
}
}
########
# NAME
# asmcmdfgrp_chfg_end
#
# DESCRIPTION
# This function processes the end of xml tags in chfg.
#
# PARAMETERS
# expat (IN) - expat parser object
# element (IN) - tag element name
#
# RETURNS
# Null.
#
# NOTES
# Only asmcmdfgrp_process_chfg() calls this function.
########
sub asmcmdfgrp_chfg_end
{
my ($expat, $element) = @_;
pop @asmcmdfgrp_parser_state;
if ($element eq 'filegroup')
{
if (@asmcmdfgrp_parser_ppty > 0)
{
$fgstmt .= uc "SET " . join(', ', @asmcmdfgrp_parser_ppty);
@asmcmdfgrp_parser_ppty = ();
}
}
}
########
# NAME
# asmcmdfgrp_chfg_char
#
# DESCRIPTION
# This function processes the text value of xml node in chfg.
#
# PARAMETERS
# expat (IN) - expat parser object
# string (IN) - one line of text from text node
#
# RETURNS
# Null.
#
# NOTES
# Only asmcmdfgrp_process_chfg() calls this function.
########
sub asmcmdfgrp_chfg_char
{
my ($expat, $string) = @_ ;
# in case of multi-line, this callback is called for each line,
# append and collect all lines together
if ( length (chomp($string)) > 0 )
{
$asmcmdfgrp_parser_text .= $string ;
}
}
########
# NAME
# asmcmdfgrp_process_chfg
#
# DESCRIPTION
# This function changes the attributes of a file group.
#
# PARAMETERS
# dbh (IN) - initialized database handle, must be non-null.
#
# RETURNS
# Null.
#
# NOTES
# Only asmcmdfgrp_process_cmd() can call this routine.
########
sub asmcmdfgrp_process_chfg
{
my ($dbh) = shift;
my (%args); # Argument hash used by getopts(). #
my ($args_ref);
my (%norm); # See asmcmdshare_normalize_path() return value comments. #
my ($ret); # asmcmdfgrp_parse_int_args() return value. #
my ($path); # Look under this path. #
my ($maxval); # Reference index value for non-directory aliases in 10gR2. #
my ($ref_id); # Reference index value for an alias entry. #
my ($gnum); # Disk group number. #
my (@eargs); # Array of error arguments. #
my (@list); # List of returned results from the select statement. #
my ($row); # One row results in @list. #
my ($hdls);
my ($parser);
my ($file);
my ($string_args);
$xml_error = 0;
# Get option parameters, if any.
$ret = asmcmdfgrp_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
return unless defined ($ret);
$args_ref = $args{'chfg'};
# check for a configuration file
if ($args_ref->[0] =~ m/\.xml$/)
{
my ($rc) = asmcmdshare_xml_exists($args_ref->[0]);
return unless defined($rc);
$file = $args_ref->[0];
}
else
{
# The argument does not look like an XML file name. We'll try to parse it
# as an XML string.
$string_args = join(' ', @{$args_ref});
}
@asmcmdfgrp_parser_state = ();
$fgstmt = "";
# We do not expect any text values for any nodes.
$asmcmdfgrp_parser_text = "" ;
# specify the handler callbacks
$hdls = { Start => \&asmcmdfgrp_chfg_start,
End => \&asmcmdfgrp_chfg_end,
Char => \&asmcmdfgrp_chfg_char };
$parser = XML::Parser->new(Handlers => $hdls,
ErrorContext => 5);
eval
{
if (defined($file))
{
$parser->parsefile($file);
}
else
{
$parser->parse($string_args);
}
};
if (asmcmdxmlexceptions::catch())
{
my (@msg, $err);
$err = asmcmdxmlexceptions::getErrmsg();
@msg = split(/\n/, $err);
if ($msg[$#msg] =~ m/Parser.pm/)
{
pop @msg;
}
$err = join("\n", @msg) ."\n";
@eargs = ($err);
asmcmdshare_error_msg(9395, \@eargs);
return;
}
# error out, if any of the nodes has text values. simply print the text.
# $asmcmddisk_parser_text = trim($asmcmddisk_parser_text);
$asmcmdfgrp_parser_text =~ s/\s+//;
if (length($asmcmdfgrp_parser_text) > 0)
{
$xml_error = 1 ;
@eargs = ($asmcmdfgrp_parser_text);
asmcmdshare_error_msg(9395, \@eargs);
return ;
}
if ($xml_error == 1)
{
return;
}
# Run SQL. #
asmcmdshare_trace(1, $fgstmt, 'y', 'n');
$ret = asmcmdshare_do_stmt($dbh, $fgstmt);
}
########
# NAME
# asmcmdfgrp_process_lsfg
#
# DESCRIPTION
# This function lists the properties of a file group.
#
# PARAMETERS
# dbh (IN) - initialized database handle, must be non-null.
#
# RETURNS
# Null.
#
# NOTES
# Only asmcmdfgrp_process_cmd() can call this routine.
########
sub asmcmdfgrp_process_lsfg
{
my ($dbh) = shift;
my ($gnum) = undef;
my (@ctype) = (' ', 'DATABASE', 'CLUSTER', 'VOLUME');
my (@fglist) = ();
my (@what) = ();
my (@from) = ();
my (@where) = ();
my (@order) = ();
my (@what_print);
my (%args);
my ($ret);
my ($fgname);
my ($sth);
my ($qry);
my (@tmp_cols);
my (%min_col_wid);
my ($print_format);
my ($print_string);
my ($i, $k, $v, $row, $h);
# Get option parameters, if any.
$ret = asmcmdfgrp_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
return unless defined ($ret);
if (defined($args{'G'}))
{
$gnum = asmcmdshare_get_gnum_from_gname($dbh, $args{'G'});
if (!defined ($gnum))
{
my (@eargs) = ($args{'G'});
asmcmdshare_error_msg(8001, \@eargs);
return;
}
}
if (defined($args{'filegroup'}))
{
$fgname = uc $args{'filegroup'};
unless (defined(asmcmdshare_filegroup_exists($dbh, $fgname)))
{
my (@eargs) = ($args{'filegroup'});
asmcmdshare_error_msg(8609, \@eargs);
return;
}
}
push (@what, 'v$asm_filegroup.name as file_group');
push (@what, 'v$asm_diskgroup.name as disk_group');
@what_print = ();
push (@what_print, $asmcmdfgrp_lsfg_header{'file_group'});
push (@what_print, $asmcmdfgrp_lsfg_header{'disk_group'});
push (@from, 'v$asm_filegroup');
push (@from, 'v$asm_diskgroup');
push (@where, 'v$asm_diskgroup.group_number = '.
'v$asm_filegroup.group_number');
if (defined($fgname))
{
# Fetch data from V$ASM_FILEGROUP_PROPERTY as well
push (@what, 'v$asm_filegroup_property.name as property');
push (@what, 'v$asm_filegroup_property.value');
push (@what, 'v$asm_filegroup_property.file_type');
push (@what_print, $asmcmdfgrp_lsfg_header{'property'});
push (@what_print, $asmcmdfgrp_lsfg_header{'value'});
push (@what_print, $asmcmdfgrp_lsfg_header{'file_type'});
push (@from, 'v$asm_filegroup_property');
push (@order, 'v$asm_filegroup_property.group_number');
push (@order, 'v$asm_filegroup_property.filegroup_number');
push (@where, "v\$asm_filegroup.name = '$fgname'");
push (@where, 'v$asm_filegroup.filegroup_number = '.
'v$asm_filegroup_property.filegroup_number');
push (@where, 'v$asm_filegroup.group_number = '.
'v$asm_filegroup_property.group_number');
push (@where, 'v$asm_filegroup_property.filegroup_number = ' .
'v$asm_filegroup.filegroup_number');
if (defined($gnum))
{
push (@where, "v\$asm_filegroup_property.group_number = '$gnum'");
}
}
else
{
# Fetch data from V$ASM_QUOTAGROUP as well
push (@what, 'v$asm_quotagroup.name as quota_group');
push (@what, 'v$asm_filegroup.used_quota_mb as used_quota_mb');
push (@what, 'v$asm_filegroup.client_name');
push (@what, 'v$asm_filegroup.client_type');
push (@what_print, $asmcmdfgrp_lsfg_header{'quota_group'});
push (@what_print, $asmcmdfgrp_lsfg_header{'used_quota_mb'});
push (@what_print, $asmcmdfgrp_lsfg_header{'client_name'});
push (@what_print, $asmcmdfgrp_lsfg_header{'client_type'});
push (@order, 'v$asm_filegroup.filegroup_number');
push (@order, 'v$asm_filegroup.client_type');
push (@order, 'v$asm_diskgroup.group_number');
push (@from, 'v$asm_quotagroup');
push (@where, 'v$asm_diskgroup.group_number = '.
'v$asm_quotagroup.group_number');
push (@where, 'v$asm_quotagroup.quotagroup_number = '.
'v$asm_filegroup.quotagroup_number');
}
if (defined($gnum))
{
push (@where, "v\$asm_filegroup.group_number = '$gnum'");
}
$sth = asmcmdshare_do_construct_select($dbh, \@what, \@from, \@where,
\@order);
@tmp_cols = @{$sth->{NAME}};
@what = map { lc $_ } @tmp_cols;
# Initialize the min_col_wid array
%min_col_wid = ();
foreach (@what)
{
$min_col_wid{$_} = length($asmcmdfgrp_lsfg_header{$_});
}
# Get the rows
while (defined($row = asmcmdshare_fetch($sth)))
{
my (%info) = ();
while (($k,$v) = each(%{$row}))
{
$k =~ tr/[A-Z]/[a-z]/;
$v = '' unless (defined($v));
$info{$k} = $v;
if (defined($min_col_wid{$k}))
{
$min_col_wid{$k} = max($min_col_wid{$k}, length($v));
}
else
{
$min_col_wid{$k} = length($v);
}
}
push (@fglist, \%info);
}
asmcmdshare_finish($sth);
#create print format
$print_format = '';
foreach (@what)
{
$print_format .= "%-" . $min_col_wid{$_} . "s " if (defined($_));
}
$print_format .= "\n";
#print header if not suppressed and if #rows >= 1
if (defined ($args{'suppressheader'}) || ($#fglist lt 0))
{
@what_print = ();
}
else
{
$print_string = sprintf($print_format, @what_print);
asmcmdshare_print($print_string);
}
#print rows
foreach $h (@fglist)
{
@what_print = ();
foreach (@what)
{
if (length($h->{$_}) == 0)
{
# If the field is empty string, print a blank space instead
push (@what_print, ' ');
}
elsif (/client_type/)
{
# 23232867: Only client_type field must be mapped to the strings stored
# at @ctype array.
push (@what_print, $ctype[$h->{$_}]);
}
else
{
push (@what_print, $h->{$_});
}
}
$print_string = sprintf($print_format, @what_print);
asmcmdshare_print($print_string);
}
return;
}
########
# NAME
# asmcmdfgrp_process_help
#
# DESCRIPTION
# This function is the help function for the ASMCMDfgrp module.
#
# PARAMETERS
# command (IN) - display the help message for this command.
#
# RETURNS
# 1 if command found; 0 otherwise.
########
sub asmcmdfgrp_process_help
{
my ($command) = shift; # User-specified argument; show help on $cmd. #
my ($syntax); # Command syntax for $cmd. #
my ($desc); # Command description for $cmd. #
my ($succ) = 0; # 1 if command found, 0 otherwise. #
if (asmcmdfgrp_is_cmd ($command))
{ # User specified a command name to look up. #
$desc = asmcmdshare_get_help_desc($command);
asmcmdshare_print "$desc\n" ;#.
$succ = 1;
}
return $succ;
}
########
# NAME
# asmcmdfgrp_is_cmd
#
# DESCRIPTION
# This routine checks if a user-entered command is one of the known
# ASMCMD internal commands that belong to the ASMCMDfgrp module.
#
# PARAMETERS
# arg (IN) - user-entered command name string.
#
# RETURNS
# True if $arg is one of the known commands, false otherwise.
########
sub asmcmdfgrp_is_cmd
{
my ($arg) = shift;
my (%cmdhash) = (mkfg => 'mkfg',
rmfg => 'rmfg',
chfg => 'chfg',
lsfg => 'lsfg',
mvfile => 'mvfile');
return defined ( $cmdhash{ $arg } );
}
########
# NAME
# asmcmdfgrp_is_wildcard_cmd
#
# DESCRIPTION
# This routine determines if an ASMCMDFGRP command allows the use
# of wild cards.
#
# PARAMETERS
# arg (IN) - user-entered command name string.
#
# RETURNS
# True if $arg is a command that can take wildcards as part of its argument,
# false otherwise.
########
sub asmcmdfgrp_is_wildcard_cmd
{
my ($arg) = shift;
my (%cmdhash); # Empty hash; no ASMCMDFGRP command supports wildcards. #
return defined ( $cmdhash{ $arg } );
}
########
# NAME
# asmcmdfgrp_is_no_instance_cmd
#
# DESCRIPTION
# This routine determines if a command can run without an ASM instance.
#
# PARAMETERS
# arg (IN) - user-entered command name string.
#
# RETURNS
# 1 if $arg is a command that can run without an ASM instance or it does not
# belong to this module
# 0 if $arg is a command that needs to connect to an ASM instance
# -1 if $arg is a command that may use an ASM instance.
#
# NOTES
# The asmcmdfgrp module currently supports no command that can run
# without an ASM instance.
########
sub asmcmdfgrp_is_no_instance_cmd
{
my ($arg) = shift;
my ($rc);
return 1 unless defined($asmcmdfgrp_cmds{$arg});
$rc = asmcmdshare_get_cmd_noinst($arg);
if ($rc eq "true")
{
return 1;
}
elsif ($rc eq "undef")
{
return -1;
}
return 0;
}
########
# NAME
# asmcmdfgrp_parse_int_args
#
# DESCRIPTION
# This routine parses the arguments for flag options for ASMCMDfgrp
# internal commands.
#
# PARAMETERS
# cmd (IN) - user-entered command name string.
# args_ref (OUT) - hash of user-specified flag options for a command,
# populated by getopts().
#
# RETURNS
# Zero on success; undefined on error.
#
# NOTES
# $cmd must already be verified as a valid ASMCMDfgrp internal command.
########
sub asmcmdfgrp_parse_int_args
{
my ($cmd, $args_ref) = @_;
my (@string);
my ($key);
# Build the list of options to parse using GetOptions
if ($asmcmdfgrp_cmds{ $cmd }{ flags })
{
foreach $key (keys %{$asmcmdfgrp_cmds{ $cmd }{ flags }})
{
push(@string, $key);
}
}
# Use asmcmdparser_parse_issued_command() from the asmcmdparser package to
# parse arguments for internal commands. These arguments are stored in @ARGV.
if (!asmcmdparser_parse_issued_command($cmd, $args_ref,\@string))
{
# Print correct command format if syntax error. #
asmcmdfgrp_syntax_error($cmd);
return undef;
}
return 0;
}
########
# NAME
# asmcmdfgrp_syntax_error
#
# DESCRIPTION
# This function prints the correct syntax for a command to STDERR, used
# when there is a syntax error. This function is responsible for
# only ASMCMDfgrp commands.
#
# PARAMETERS
# cmd (IN) - user-entered command name string.
#
# RETURNS
# 1 if the command belongs to this module; 0 if command not found.
#
# NOTES
# These errors are user-errors and not internal errors. They are of type
# record, not signal.
#
# N.B. Functions in this module can call this function directly, without
# calling the asmcmdshare::asmcmdshare_syntax_error equivalent. The
# latter is used only by the asmcmdcore module.
########
sub asmcmdfgrp_syntax_error
{
my ($cmd) = shift;
my ($cmd_syntax); # Correct syntax for $cmd. #
my ($succ) = 0;
$cmd_syntax = asmcmdfgrp_get_cmd_syntax($cmd); # Get syntax for $cmd. #
if (defined ($cmd_syntax))
{
asmcmdshare_printstderr("usage: $cmd_syntax\n");
$succ = 1;
}
return $succ;
}
########
# NAME
# asmcmdfgrp_get_cmd_desc
#
# DESCRIPTION
# This routine returns the help description of the command specified by $cmd.
#
# PARAMETERS
# cmd (IN) - the name of the command of which we're looking up the
# description.
#
# RETURNS
# The description paragraph(s) for command $cmd; undefined if $cmd does not
# exist.
#
# NOTES
# IMPORTANT: the commands descriptions must be preceded by eight (8) spaces
# of indentation! This formatting is mandatory.
########
sub asmcmdfgrp_get_cmd_desc
{
my ($cmd) = shift;
my (%cmd_desc); # Hash storing the description for each internal command. #
$cmd_desc{'mkfg'} = '
Adds a filegroup to the specified disk group.';
$cmd_desc{'rmfg'} = '
Deletes a file group.';
$cmd_desc{'chfg'} = '
Changes property values for the specified file group.';
$cmd_desc{'lsfg'} = '
Lists the existing filegroups or the file group properties if a file' . "\n" .'
group name is specified.';
return $cmd_desc{$cmd};
}
########
# NAME
# asmcmdfgrp_get_cmd_syntax
#
# DESCRIPTION
# This routine returns the help syntax of the command specified by $cmd.
#
# PARAMETERS
# cmd (IN) - the name of the command of which we're looking up the
# syntax.
#
# RETURNS
# The syntax for command $cmd; undefined if $cmd does not exist.
########
sub asmcmdfgrp_get_cmd_syntax
{
my ($cmd) = shift;
my (%cmd_syntax); # Hash storing the syntax for each internal command. #
$cmd_syntax{'mkfg'} = q(mkfg {<config_file.xml> | <'contents_of_xml_file'>});
# $cmd_syntax{'rmfg'} = 'rmfg [-r] <diskgroup> <filegroup>';
$cmd_syntax{'rmfg'} = 'rmfg <diskgroup> <filegroup>';
$cmd_syntax{'chfg'} = q(chfg {<config_file.xml> | <'contents_of_xml_file'>});
$cmd_syntax{'lsfg'} = 'lsfg [--suppressheader] [-G <diskgroup>] [--filegroup'.
' <filegroup>]';
return $cmd_syntax{$cmd};
}
########
# NAME
# asmcmdfgrp_get_asmcmd_cmds
#
# DESCRIPTION
# This routine constructs a string that contains a list of the names of all
# ASMCMD internal commands and returns this string.
#
# PARAMETERS
# None.
#
# RETURNS
# A string contain a list of the names of all ASMCMD internal commands.
#
# NOTES
# Used by the help command and by the error command when the user enters
# an invalid internal command.
#
# IMPORTANT: the commands names must be preceded by eight (8) spaces of
# indention! This formatting is mandatory.
########
sub asmcmdfgrp_get_asmcmd_cmds
{
return asmcmdshare_filter_invisible_cmds(%asmcmdfgrp_cmds);
}
1;
OHA YOOOO