| DataFax/StudySubs.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 13 | 15 | 86.6 |
| branch | n/a | ||
| condition | n/a | ||
| subroutine | 5 | 5 | 100.0 |
| pod | n/a | ||
| total | 18 | 20 | 90.0 |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | package DataFax::StudySubs; | ||||||
| 2 | |||||||
| 3 | 1 | 1 | 38655 | use strict; | |||
| 1 | 2 | ||||||
| 1 | 448 | ||||||
| 4 | 1 | 1 | 7 | use vars qw(@ISA $VERSION @EXPORT @EXPORT_OK %EXPORT_TAGS); | |||
| 1 | 2 | ||||||
| 1 | 304 | ||||||
| 5 | 1 | 1 | 7 | use Carp; | |||
| 1 | 7 | ||||||
| 1 | 94 | ||||||
| 6 | 1 | 1 | 3187 | use IO::File; | |||
| 1 | 14849 | ||||||
| 1 | 125 | ||||||
| 7 | 1 | 1 | 1584 | use Net::Rexec 'rexec'; | |||
| 0 | |||||||
| 0 | |||||||
| 8 | |||||||
| 9 | $VERSION = 0.10; | ||||||
| 10 | use DataFax; | ||||||
| 11 | @ISA = qw(Exporter DataFax); | ||||||
| 12 | @EXPORT = qw(dfparam disp_param debug_level echo_msg get_dfparam); | ||||||
| 13 | @EXPORT_OK = qw(dfparam disp_param debug_level echo_msg get_dfparam | ||||||
| 14 | exec_cmd | ||||||
| 15 | ); | ||||||
| 16 | %EXPORT_TAGS= ( | ||||||
| 17 | all =>[@EXPORT_OK], | ||||||
| 18 | echo_msg=>[qw(dfparam disp_param debug_level echo_msg get_dfparam)], | ||||||
| 19 | param =>[qw(dfparam disp_param get_dfparam)], | ||||||
| 20 | cmd =>[qw(exec_cmd)], | ||||||
| 21 | ); | ||||||
| 22 | |||||||
| 23 | =head1 NAME | ||||||
| 24 | |||||||
| 25 | DataFax::StudySubs - DataFax common sub routines | ||||||
| 26 | |||||||
| 27 | =head1 SYNOPSIS | ||||||
| 28 | |||||||
| 29 | use DataFax::StudySubs qw(:all); | ||||||
| 30 | |||||||
| 31 | =head1 DESCRIPTION | ||||||
| 32 | |||||||
| 33 | This class contains the common sub-routines used in DataFax. | ||||||
| 34 | |||||||
| 35 | =cut | ||||||
| 36 | |||||||
| 37 | sub new { | ||||||
| 38 | my ($s, %args) = @_; | ||||||
| 39 | return $s->SUPER::new(%args); | ||||||
| 40 | } | ||||||
| 41 | |||||||
| 42 | # --------------------------------------------------------------------- | ||||||
| 43 | |||||||
| 44 | =head1 Export Tag: all | ||||||
| 45 | |||||||
| 46 | The :all tag includes the all the methods in this module. | ||||||
| 47 | |||||||
| 48 | use DataFax::StudySubs qw(:all); | ||||||
| 49 | |||||||
| 50 | It includes the following sub-routines: | ||||||
| 51 | |||||||
| 52 | =head2 dfparam($var, $ar[,$val]) | ||||||
| 53 | |||||||
| 54 | Input variables: | ||||||
| 55 | |||||||
| 56 | $var - variable name | ||||||
| 57 | $ar - parameter hash or array ref | ||||||
| 58 | $val - value to be added or assigned | ||||||
| 59 | |||||||
| 60 | Variables used or routines called: | ||||||
| 61 | |||||||
| 62 | None | ||||||
| 63 | |||||||
| 64 | How to use: | ||||||
| 65 | |||||||
| 66 | use DataFax::DFstudyDB qw(dfparam); | ||||||
| 67 | my $ar = {a=>1,b=>25}; | ||||||
| 68 | my $br = [1,2,5,10]; | ||||||
| 69 | # for hash ref | ||||||
| 70 | my $va = $self->dfparam('a',$ar); # set $va = 1 | ||||||
| 71 | my $v1 = $self->dfparam('v1',$ar); # set $v1 = "" | ||||||
| 72 | my $v2 = $self->dfparam('b',$ar); # set $v2 = 25 | ||||||
| 73 | # for array ref | ||||||
| 74 | my $v3 = $self->dfparam(0,$br); # set $v3 = 1 | ||||||
| 75 | my $v4 = $self->dfparam(3,$br); # set $v4 = 10 | ||||||
| 76 | # add or assign values and return array ref | ||||||
| 77 | $self->dfparam('c',$ar,30); # set $ar->{c} = 30 | ||||||
| 78 | $self->dfparam(5,$br,50); # set $br->[5] = 50 | ||||||
| 79 | |||||||
| 80 | Return: $r - the value in the hash or empty string or array ref. | ||||||
| 81 | |||||||
| 82 | This method gets and sets the $var in $ar. If the varirable | ||||||
| 83 | does not exists in $ar, it tries in $self as well for 'get'. | ||||||
| 84 | |||||||
| 85 | =cut | ||||||
| 86 | |||||||
| 87 | sub dfparam { | ||||||
| 88 | my ($s, $v, $r) = @_; | ||||||
| 89 | if ($#_>2) { # there is a third input | ||||||
| 90 | $r->[$v] = $_[3] if $v =~ /^\d+$/ && ref($r) =~ /ARRAY/; | ||||||
| 91 | $r->{$v} = $_[3] if ref($r) =~ /HASH/ || ref $r; | ||||||
| 92 | return ; | ||||||
| 93 | } | ||||||
| 94 | # if only variable name and the name exists in the class object | ||||||
| 95 | return $s->{$v} if $#_==1 && exists $s->{$v}; | ||||||
| 96 | # return blank if no $v or $r is not array, hash nor object | ||||||
| 97 | return "" if $v =~ /^\s*$/; | ||||||
| 98 | return $s->{$v} if exists $s->{$v} && !$r; | ||||||
| 99 | return "" if ! ref($r); | ||||||
| 100 | return "" if $v !~ /^\d+$/ && ref($r) =~ /ARRAY/; | ||||||
| 101 | |||||||
| 102 | return (exists $r->[$v])?$r->[$v]:"" if ref($r) =~ /^ARRAY/; | ||||||
| 103 | # if $r = $s, then ref $r will make it sure to catch that as well | ||||||
| 104 | return (exists $r->{$v})?$r->{$v}:((exists $s->{$v})?$s->{$v}:"") | ||||||
| 105 | if ref($r) =~ /^HASH/ || ref $r; | ||||||
| 106 | return ""; # catch all | ||||||
| 107 | } | ||||||
| 108 | |||||||
| 109 | =head2 get_dfparam($vs, $ar) | ||||||
| 110 | |||||||
| 111 | Input variables: | ||||||
| 112 | |||||||
| 113 | $vs - a list of variable names separated by comma | ||||||
| 114 | $ar - parameter hash or array ref | ||||||
| 115 | |||||||
| 116 | Variables used or routines called: | ||||||
| 117 | |||||||
| 118 | dfparam - get individual parameter | ||||||
| 119 | |||||||
| 120 | How to use: | ||||||
| 121 | |||||||
| 122 | use DataFax::DFstudyDB qw(:all); | ||||||
| 123 | my $ar = {a=>1,b=>25}; | ||||||
| 124 | my ($va, $vb) = $self->get_dfparam('a,b',$ar); | ||||||
| 125 | |||||||
| 126 | Return: array or array ref | ||||||
| 127 | |||||||
| 128 | This method gets multiple values for listed variables. | ||||||
| 129 | |||||||
| 130 | =cut | ||||||
| 131 | |||||||
| 132 | sub get_dfparam { | ||||||
| 133 | my $s = shift; | ||||||
| 134 | my ($vs, $r) = @_; | ||||||
| 135 | return () if ! $vs; | ||||||
| 136 | my $p = []; | ||||||
| 137 | $vs =~ s/\s+//g; # remove any spaces | ||||||
| 138 | foreach my $k (split /,/, $vs) { | ||||||
| 139 | push @$p, $s->dfparam($k, $r); | ||||||
| 140 | } | ||||||
| 141 | return wantarray ? @$p : $p; | ||||||
| 142 | } | ||||||
| 143 | |||||||
| 144 | =head2 exec_cmd ($cmd, $pr) | ||||||
| 145 | |||||||
| 146 | Input variables: | ||||||
| 147 | |||||||
| 148 | $cmd - a full unix command with paraemters and arguments | ||||||
| 149 | $pr - parameter hash ref | ||||||
| 150 | datafax_host - DataFax host name or ip address | ||||||
| 151 | local_host - local host name or ip address | ||||||
| 152 | datafax_usr - DataFax user name | ||||||
| 153 | datafax_pwd - DataFax user password | ||||||
| 154 | |||||||
| 155 | Variables used or routines called: | ||||||
| 156 | |||||||
| 157 | get_dfparam - get values for multiple parameters | ||||||
| 158 | |||||||
| 159 | How to use: | ||||||
| 160 | |||||||
| 161 | use DataFax::DFstudyDB qw(:all); | ||||||
| 162 | # Case 1: hosts are different and without id and password | ||||||
| 163 | my $cmd = "cat /my/dir/file.txt"; | ||||||
| 164 | my $pr = {datafax_host=>'dfsvr',local_host='svr2'}; | ||||||
| 165 | my @a = $self->exec_cmd($cmd,$pr); # uses rsh to run the cmd | ||||||
| 166 | |||||||
| 167 | # Case 2: different hosts with id and password | ||||||
| 168 | my $pr = {datafax_host=>'dfsvr',local_host='svr2', | ||||||
| 169 | datafax_usr=>'fusr', datafax_pwd=>'pwd' }; | ||||||
| 170 | my @a = $self->exec_cmd($cmd,$pr); # uses rexec | ||||||
| 171 | |||||||
| 172 | # Case 2: hosts are the same | ||||||
| 173 | my $pr = {datafax_host=>'dfsvr',local_host='dfsvr'}; | ||||||
| 174 | my $ar = $self->exec_cmd('/my/file.txt',$pr); # case 2: | ||||||
| 175 | |||||||
| 176 | Return: array or array ref | ||||||
| 177 | |||||||
| 178 | This method opens a file or runs a command and return the contents | ||||||
| 179 | in array or array ref. | ||||||
| 180 | |||||||
| 181 | =cut | ||||||
| 182 | |||||||
| 183 | sub exec_cmd { | ||||||
| 184 | my $s = shift; | ||||||
| 185 | my ($cmd, $pr) = @_; | ||||||
| 186 | my $vs='datafax_host,local_host,datafax_usr,datafax_pwd'; | ||||||
| 187 | my ($dfh,$lsv,$usr,$pwd) = $s->get_dfparam($vs,$pr); | ||||||
| 188 | $lsv = `hostname` if ! $lsv; | ||||||
| 189 | my ($rc, @a); | ||||||
| 190 | if ($dfh ne $lsv) { | ||||||
| 191 | # croak "ERR: no user name for remote access.\n" if ! $usr; | ||||||
| 192 | # croak "ERR: no password for user $usr.\n" if ! $pwd; | ||||||
| 193 | if ($usr && $pwd) { # use rexec | ||||||
| 194 | $s->echo_msg(" CMD: $cmd at $dfh for user $usr...", 1); | ||||||
| 195 | ($rc, @a) = rexec($dfh, $cmd, $usr, $pwd); | ||||||
| 196 | $rc == 0 || carp " WARN: could not run $cmd on $dfh.\n"; | ||||||
| 197 | } else { # use rsh | ||||||
| 198 | my $u = "rsh $dfh $cmd |"; | ||||||
| 199 | my $fh = new IO::File; | ||||||
| 200 | $fh->open("$u")||carp " WARN: could not run $u: $!.\n"; | ||||||
| 201 | @a=<$fh>; close($fh); | ||||||
| 202 | } | ||||||
| 203 | } else { # use perl module | ||||||
| 204 | $s->echo_msg(" CMD: $cmd at $lsv...", 1); | ||||||
| 205 | my $fh = new IO::File; | ||||||
| 206 | $fh->open("$cmd") || carp " WARN: could not run $cmd: $!.\n"; | ||||||
| 207 | @a=<$fh>; close($fh); | ||||||
| 208 | } | ||||||
| 209 | return wantarray ? @a : \@a; | ||||||
| 210 | } | ||||||
| 211 | |||||||
| 212 | =head2 debug_level($n) | ||||||
| 213 | |||||||
| 214 | Input variables: | ||||||
| 215 | |||||||
| 216 | $n - a number between 0 and 100. It specifies the | ||||||
| 217 | level of messages that you would like to | ||||||
| 218 | display. The higher the number, the more | ||||||
| 219 | detailed messages that you will get. | ||||||
| 220 | |||||||
| 221 | Variables used or routines called: None. | ||||||
| 222 | |||||||
| 223 | How to use: | ||||||
| 224 | |||||||
| 225 | $self->debug_level(2); # set the message level to 2 | ||||||
| 226 | print $self->debug_level; # print current message level | ||||||
| 227 | |||||||
| 228 | Return: the debug level or set the debug level. | ||||||
| 229 | |||||||
| 230 | =cut | ||||||
| 231 | |||||||
| 232 | sub debug_level { | ||||||
| 233 | # my ($c_pkg,$c_fn,$c_ln) = caller; | ||||||
| 234 | # my $s = ref($_[0])?shift:(bless {}, $c_pkg); | ||||||
| 235 | my $s = shift; | ||||||
| 236 | croak "ERR: Too many args to debug." if @_ > 1; | ||||||
| 237 | @_ ? ($s->{_debug_level}=shift) : return $s->{_debug_level}; | ||||||
| 238 | } | ||||||
| 239 | |||||||
| 240 | =head2 echo_msg($msg, $lvl, $fh) | ||||||
| 241 | |||||||
| 242 | Input variables: | ||||||
| 243 | |||||||
| 244 | $msg - the message to be displayed. No newline | ||||||
| 245 | is needed in the end of the message. It | ||||||
| 246 | will add the newline code at the end of | ||||||
| 247 | the message. | ||||||
| 248 | $lvl - the message level is assigned to the message. | ||||||
| 249 | If it is higher than the debug level, then | ||||||
| 250 | the message will not be displayed. | ||||||
| 251 | $fh - file handler, or set the file hanlder in this parameter | ||||||
| 252 | $ENV{FH_DEBUG_LOG} | ||||||
| 253 | |||||||
| 254 | Variables used or routines called: | ||||||
| 255 | |||||||
| 256 | debug_level - get debug level. | ||||||
| 257 | |||||||
| 258 | How to use: | ||||||
| 259 | |||||||
| 260 | # default msg level to 0 | ||||||
| 261 | $self->echo_msg('This is a test"); | ||||||
| 262 | # set the msg level to 2 | ||||||
| 263 | $self->echo_msg('This is a test", 2); | ||||||
| 264 | |||||||
| 265 | Return: None. | ||||||
| 266 | |||||||
| 267 | This method will display message or a hash array based on I |
||||||
| 268 | level. If I |
||||||
| 269 | displayed. If I |
||||||
| 270 | level ($lvl) is less than or equal to '2'. If you call this | ||||||
| 271 | method without providing a message level, the message level ($lvl) is | ||||||
| 272 | default to '0'. Of course, if no message is provided to the method, | ||||||
| 273 | it will be quietly returned. | ||||||
| 274 | |||||||
| 275 | This is how you can call I |
||||||
| 276 | |||||||
| 277 | my $df = DataFax->new; | ||||||
| 278 | $df->echo_msg("This is a test"); # default the msg to level 0 | ||||||
| 279 | $df->echo_msg("This is a test",1); # assign the msg as level 1 msg | ||||||
| 280 | $df->echo_msg("Test again",2); # assign the msg as level 2 msg | ||||||
| 281 | $df->echo_msg($hrf,1); # assign $hrf as level 1 msg | ||||||
| 282 | $df->echo_msg($hrf,2); # assign $hrf as level 2 msg | ||||||
| 283 | |||||||
| 284 | If I |
||||||
| 285 | i.e., 0, and '1' will be displayed. The higher level messages | ||||||
| 286 | will not be displayed. | ||||||
| 287 | |||||||
| 288 | This method displays or writes the message based on debug level. | ||||||
| 289 | The filehandler is provided through $fh or $ENV{FH_DEBUG_LOG}, and | ||||||
| 290 | the outputs are written to the file. | ||||||
| 291 | |||||||
| 292 | =cut | ||||||
| 293 | |||||||
| 294 | sub echo_msg { | ||||||
| 295 | # my ($c_pkg,$c_fn,$c_ln) = caller; | ||||||
| 296 | # my $self = ref($_[0])?shift:(bless {},$c_pkg); | ||||||
| 297 | my $self = shift; | ||||||
| 298 | my ($msg,$lvl, $fh) = @_; | ||||||
| 299 | $fh = (exists $ENV{FH_DEBUG_LOG})?$ENV{FH_DEBUG_LOG}:""; | ||||||
| 300 | $fh = "" if !$fh || ($fh && ref($fh) !~ /(IO::File|GLOB)/); | ||||||
| 301 | if (!defined($msg)) { return; } # return if no msg | ||||||
| 302 | if (!defined($lvl)) { $lvl = 0; } # default level to 0 | ||||||
| 303 | my $class = ref($self)||$self; # get class name | ||||||
| 304 | my $dbg = $self->debug_level; # get debug level | ||||||
| 305 | if (!$dbg) { return; } # return if not debug | ||||||
| 306 | my $ref = ref($msg); | ||||||
| 307 | if ($ref eq $class || $ref =~ /(ARRAY|HASH)/) { | ||||||
| 308 | if ($lvl <= $dbg) { $self->disp_param($msg); } | ||||||
| 309 | } else { | ||||||
| 310 | $msg = "$msg" if exists $ENV{QUERY_STRING} && |
||||||
| 311 | $msg =~ /^\s*\d+\.\s+\w+/; | ||||||
| 312 | $msg =~ s/\/(\w+)\@/\/****\@/g if $msg =~ /(\w+)\/(\w+)\@(\w+)/; | ||||||
| 313 | $msg = "$msg\n"; | ||||||
| 314 | $msg =~ s/\n/ \n/gm if exists $ENV{QUERY_STRING}; |
||||||
| 315 | if ($lvl <= $dbg) { | ||||||
| 316 | if ($fh) { print $fh $msg; } else { print $msg; } | ||||||
| 317 | } | ||||||
| 318 | } | ||||||
| 319 | } | ||||||
| 320 | |||||||
| 321 | =head2 disp_param($arf,$lzp, $fh) | ||||||
| 322 | |||||||
| 323 | Input variables: | ||||||
| 324 | |||||||
| 325 | $arf - array reference | ||||||
| 326 | $lzp - number of blank space indented in left | ||||||
| 327 | $fh - file handler | ||||||
| 328 | |||||||
| 329 | Variables used or routines called: | ||||||
| 330 | |||||||
| 331 | echo_msg - print debug messages | ||||||
| 332 | debug_level - set debug level | ||||||
| 333 | disp_param - recusively called | ||||||
| 334 | |||||||
| 335 | How to use: | ||||||
| 336 | |||||||
| 337 | use DataFax::StudySubs qw(:echo_msg); | ||||||
| 338 | my $self= bless {}, "main"; | ||||||
| 339 | $self->disp_param($arf); | ||||||
| 340 | |||||||
| 341 | Return: Display the content of the array. | ||||||
| 342 | |||||||
| 343 | This method recursively displays the contents of an array. If a | ||||||
| 344 | filehandler is provided through $fh or $ENV{FH_DEBUG_LOG}, the outputs | ||||||
| 345 | are written to the file. | ||||||
| 346 | |||||||
| 347 | =cut | ||||||
| 348 | |||||||
| 349 | sub disp_param { | ||||||
| 350 | my ($self, $hrf, $lzp, $fh) = @_; | ||||||
| 351 | my $otp = ref $hrf; | ||||||
| 352 | $self->echo_msg(" - displaying parameters in $otp..."); | ||||||
| 353 | $fh = (exists $ENV{FH_DEBUG_LOG})?$ENV{FH_DEBUG_LOG}:""; | ||||||
| 354 | $fh = "" if !$fh || ($fh && ref($fh) !~ /(IO::File|GLOB)/); | ||||||
| 355 | if (!$lzp) { $lzp = 15; } else { $lzp +=4; } | ||||||
| 356 | my $fmt; | ||||||
| 357 | if (exists $ENV{QUERY_STRING}) { | ||||||
| 358 | # $fmt = "%${lzp}s = %-30s \n"; |
||||||
| 359 | $fmt = (" " x $lzp) . "%s = %-30s \n"; |
||||||
| 360 | } else { | ||||||
| 361 | $fmt = "%${lzp}s = %-30s\n"; | ||||||
| 362 | } | ||||||
| 363 | if (!$hrf) { | ||||||
| 364 | print "Please specify an array ref.\n"; | ||||||
| 365 | return; | ||||||
| 366 | } | ||||||
| 367 | # print join "|", $self, "HRF", $hrf, ref($hrf), "\n"; | ||||||
| 368 | my ($v); | ||||||
| 369 | if (ref($hrf) eq 'HASH'|| $hrf =~ /.*=HASH/) { | ||||||
| 370 | foreach my $k (sort keys %{$hrf}) { | ||||||
| 371 | if (!defined(${$hrf}{$k})) { $v = ""; | ||||||
| 372 | } else { $v = ${$hrf}{$k}; } | ||||||
| 373 | if ($v =~ /([-\w_]+)\/(\w+)\@(\w+)/) { | ||||||
| 374 | $v =~ s{(\w+)/(\w+)\@}{$1/\*\*\*\@}g; | ||||||
| 375 | } | ||||||
| 376 | chomp $v; | ||||||
| 377 | if ($fh) { printf $fh $fmt, $k, $v; | ||||||
| 378 | } else { printf $fmt, $k, $v; } | ||||||
| 379 | if (ref($v) =~ /^(HASH|ARRAY)$/ || | ||||||
| 380 | $v =~ /.*=(HASH|ARRAY)/) { | ||||||
| 381 | my $db1 = $self->debug_level; | ||||||
| 382 | $self->debug_level(0); | ||||||
| 383 | # print "$k = ${$hrf}{$k}: @{${$hrf}{$k}}\n"; | ||||||
| 384 | $self->disp_param(${$hrf}{$k},$lzp); | ||||||
| 385 | $self->debug_level($db1); | ||||||
| 386 | if ($fh) { print $fh "\n"; } else { print "\n"; } | ||||||
| 387 | } | ||||||
| 388 | } | ||||||
| 389 | } elsif (ref($hrf) eq 'ARRAY' || $hrf =~ /.*=ARRAY/) { | ||||||
| 390 | foreach my $i (0..$#{$hrf}) { | ||||||
| 391 | if (!defined(${$hrf}[$i])) { $v = ""; | ||||||
| 392 | } else { $v = ${$hrf}[$i]; } | ||||||
| 393 | if ($v =~ /([-\w_]+)\/(\w+)\@(\w+)/) { | ||||||
| 394 | $v =~ s{(\w+)/(\w+)\@}{$1/\*\*\*\@}g; | ||||||
| 395 | } | ||||||
| 396 | chomp $v; | ||||||
| 397 | if ($fh) { printf $fh $fmt, $i, $v; | ||||||
| 398 | } else { printf $fmt, $i, $v; } | ||||||
| 399 | if (ref($v) =~ /^(HASH|ARRAY)$/ || | ||||||
| 400 | $v =~ /.*=(HASH|ARRAY)/) { | ||||||
| 401 | my $db1 = $self->debug_level; | ||||||
| 402 | $self->debug_level(0); | ||||||
| 403 | $self->disp_param(${$hrf}[$i],$lzp); | ||||||
| 404 | $self->debug_level($db1); | ||||||
| 405 | if ($fh) { print $fh "\n"; } else { print "\n"; } | ||||||
| 406 | } | ||||||
| 407 | } | ||||||
| 408 | } | ||||||
| 409 | } | ||||||
| 410 | |||||||
| 411 | 1; | ||||||
| 412 |