package FCRules;
#<copyright>
# ----------------------------------------------------------
# Sun Proprietary/Confidential Code
# Copyright 2001, Sun Microsystems, Inc. All rights reserved.
# ----------------------------------------------------------
#</copyright>


use Util;
use System;
#use FibreStat;
use Data::Dumper;
use Time::JulianDay;
use Agent;
use strict;

#lnk fail    sync loss   signal loss   sequence err   invalid word   CRC

# MMDDHH:MM:SS
sub today {
  my($this) = @_;

  my(@date) = localtime(time);
  $date[4]++; $date[5] += 1900;

  sprintf("%2.2d%2.2d%2.2d%2.2d%2.2d",
    $date[4],$date[3], $date[2], $date[1], $date[0]);
}

use vars qw ($RULES);

sub load_rules {

  return $RULES if ($RULES);
  $RULES = [];
  my($DIR) = System->get_home() . "/lib/FCRules";
  opendir(D, $DIR);

  my @rules = readdir(D); closedir(D);
  foreach my $rulefile (sort @rules) {
     next if ($rulefile !~ /\.pm$/) ;

     my $rulename = substr($rulefile, 0, -3);
     eval "require \"FCRules/$rulename.pm\"";
     my $r = "FCRules::$rulename";
     push(@$RULES, $r);
  }
  return $RULES;
}
#
# ($CIMKey, $key, $port) = FCRules->findPortKeys(...
#  $hba|$wwn|$port|$type
#

sub findPortKeys {
  my($class, $key, $info, $st) = @_;

  my($hba, $wwn, $port, $type) = split(/\|/, $key);
  my($CIMKey1, $key1, $port_desc);

  my($ctrl_port) = $port;
  
  if ($type eq "a5k") {
    my($portI) = $st->portInfo();
    my($hb) = $info->{hba}{$hba}; # hba counters came from.

    if ($hba ne "") {
      if ($portI->[0]{hba_path} =~ /$hb/) {
         $port = 0;
      } elsif ($portI->[1]{hba_path} =~ /$hb/) {
         $port = 1;
      } else {
         Debug->print2("Rule3: Cannot find $hb in portInfo on a5k $wwn");
         return ();
      }
    }
    $CIMKey1 = "$wwn.interface_board." . (($port==0) ? "A":"B");
    $key1    = "a5k:$wwn:" . ($port+1);
    $ctrl_port = $port + 1;
    $port_desc = "IB-" . (($port==0) ? "A":"B");

  } elsif ($type eq "t3") {  # |sci-sj.370-3990-01-e-d0.000814|0|t3
    my $ci;
    return undef if (!$ci);
    $ctrl_port = $port ;
    $port_desc = "Ctrl-$port";

  } else {
    $CIMKey1     = "$wwn.port.$port";
    $key1        = "$type:$wwn:$port";
    $port_desc   = "Port-$port";
  }
  return ($CIMKey1, $key1, $ctrl_port, $port_desc);

}

sub debug {
  my($class, $l) = @_;

  if ($0 =~ /rasagent/) {
     Debug->print2($l);
  } else {
     print "$l<br>\n";
  }
}
  
#
# NOT USED, now is PDM->saveLinkState in Health.pm
sub log {
  my($class, $rule, $node1, $node2, $title, $reads, $writes) = @_;
  my($info);
  return if (!$node1 || !$node2);
  my $log = System->get_home() . "/DATA/CountersLog";
  my $date = &today();

  open(O,  ">>$log");
  my($cnt) = 0;
  foreach my $l (@$reads) {
     $info .= "  $l\n";
     last if ($cnt++ > 10);
  }

  $cnt = 0;
  foreach my $l (@$writes) {
     $info .= "  $l\n";
     last if ($cnt++ > 10);
  }

  print O "$date\t$rule\t$node1\t$node2\t$title\n$info";
  close(O);
}

#
#  return linkno 0/1
#
sub a5kIsFirst {
  my($class, $hb , $a5, $port_type) = @_;
  
  my($port2, $linkno, $ses_info, $portab);
  my($a5_info)  = $a5->{info};
  my($a5_ports) = $a5->portInfo();
  my($a5_name)  = $a5_info->{name};
  my($is_first) = 0;
  my($x);
  for ($x=0; $x <= 3; $x++) {
     if ($a5_ports->[$x]{hba_path} =~ /$hb/) {
       return $x;
     }
  }
  return undef;

#  NOT USED
# IB-A  has 2 ports Port-0 and Port-1
# IB-B  has 2 ports Port-0 and Port-1

  my $gb = Util->deserialize("GBICS");
  return $linkno if (!$gb);

  $port2 = $gb->{"$a5_name:$portab"};

  if ($port2 == 0 && ($port_type eq "f")) {
    $is_first = 1; # front

  } elsif ($port2 == 1 && ($port_type eq "r")) {
    $is_first = 1; # rear

  } else {
    return undef;
  }
}


#
#  will find if the target device from /var/adm is the last disk 
#  of the a5k, the ses# is known.
#
sub a5kTargetIsLast {
  my($class, $reads, $writes, $a5, $ses_no) = @_;
  my($wwn, $disk_wwn);
  my($disks) = $a5->{disk_info};
  my(@wwns) = ();

  my($portab) = ($ses_no == 0) ? "A" : "B"; # N/U

  my($sess) = $a5->{ses_info};
  my($a5_name) = $a5->{info}{name};
  my($ses_info) = $sess->[$ses_no];

  my $gb = Util->deserialize("GBICS");

  my $port2 = $gb->{"$a5_name:$portab"};

  print "$a5_name: portWWN = $ses_info->{PortWWN} board=$portab, port=$port2<br>";

  my($l);
  foreach $l (@$reads) {
      if ($l =~ /\@w([0-9abcdef]+)/) {
        push(@wwns,$1);
      }
  }
  foreach $l (@$writes) {
      if ($l =~ /\@w([0-9abcdef]+)/) {
        push(@wwns,$1);
      }
  }
  my($fire) = 0;
  my($disk);
  my($target_disk) = undef;

  foreach $disk (keys %$disks) {
      $disk_wwn = substr($disks->{$disk}{NodeWWN}, 2) ;
      foreach $wwn (@wwns) {
         if (substr($wwn,2) eq $disk_wwn && substr($disk,1) eq "10" ) {
             if ( (($port2 == 0) && substr($disk,0,1) eq "r") ||
                  (($port2 == 1) && substr($disk,0,1) eq "f") ) {
                 print "found disk = $disk ($wwn)<br>";
                 $target_disk = $disk;
                 $fire = 1;
                 last;
             }
         }
      }
      last if ($fire);
  }
  return $target_disk;
}

1;
