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

#Name:  $
#  $Id: COMMON.pm,v 1.26 2004/11/02 21:58:41 ccadieux Exp $

use Health;
use base 'Health';
use NWS::COMMON;
use DevDB;
use Ilist;
use Message;
use Timer;
use Report;
use System;
use Events;
use strict;
use Debug;

sub revision {'$Revision: 1.26 $'}

sub EXTRA_LOGIC {
  my($hm, $key, $display_id, $rep, $orep) = @_; 

}


sub LOGIC {
  my($hm, $report) = @_;
  my($ev, $ed, $pertains, $x ,$y, $contain, $sd);
  my($orep, $key);
  my $oreport  = PDM->getOldReport($report->fileKey);
  my $rep      = $report->content;
  my($ip)      = $report->id('ip');
  $DB::single = 1;
  my $wwn      = $report->id('deviceName');
  my $id       = $report->id('display');
  my $type     = $report->id('category');
  my $volVerify= $report->id('volVerify');
  my $shortid  = $report->name();
  my $renv     = System->get_renv();


  my $mgmtLevel = $report->value('id.mgmtLevel') || 'D';
  if (!$wwn) {
     Debug->errNoRepeat(T3_NO_KEY => $ip, 24, "This $type ($ip) cannot be identified");
     return;
  }

  CIM->version("1.1");

  if ($hm->connectionEvent($wwn, $report, {method => 3} )) {  # IB / OOB
     return;
  }
  my($freq) = $renv->{audit_freq} || 7;
  my $audit = System->get_audit() ? "YES" : Timer->isXdays("Audit$wwn", $freq);
  my $run_audit;

  if (!$oreport || $audit eq "YES" ) {  # new t300 or audit time.
     my $nws_module = $hm->NWS_module();
#     $hm->discoveryEvent($report, "NWS::COMMON", $audit);
     $hm->discoveryEvent($report, $nws_module, $audit);
  }

  $orep = ($oreport)? $oreport->content() : $rep; # same report if new disco.


  $hm->locationChangeEvent($report, $rep, $orep, $wwn);

  my ($nwssystem) = CIM::Instance->new('NWS_System',[
                    [Name 		=> $wwn    ],
                    [OtherIdentifyingInfo  => $rep->get("id.device_ipno") ],
                    [SystemName         => $rep->get('id.device_name')],
                    [LogInfo            => ""  ],
                    [IP 		=> $rep->get('id.device_ipno') ],
                    [FruCount 		=> $rep->get('fru.count')  ],
                    [FruCtlrCount 	=> $rep->get('ctrl.count') ],
                    [FruDiskDriveCount 	=> $rep->get('disk.count') ],
                    [FruPowerCount 	=> $rep->get('pcu.count')    ],
                    [VolCount 		=> $rep->get('volume.count') ],
                    [SysRevision 	=> $rep->get('system._Version')],
                    [Caption            => uc($type) ],
                ]);

  my($physicalFrame) = CIM::Key->new( ['CIM_PhysicalFrame',   # key of the frame
                        Tag               => $wwn ,
                        CreationClassName => 'CIM_PhysicalFrame' ]);


  my ($j, $k);
  my $fc_comps = $hm->internal_port_components();
  foreach my $fc_comp (@$fc_comps)  {
     my $fc_fru = $fc_comp;
     my $count = $rep->{"$fc_fru.count"};

     for ($j=1; $j <= $count; $j++)     {
        my $subcount = $rep->{"$fc_fru.$j.fcport.count"};

        for ($k=1; $k <= $subcount; $k++)	{
           my $comp    = "$fc_fru.$j.fcport.$k";
           my $display = $rep->{"$comp._ElementName"};
           foreach my $el ('_CRCErrors', '_InvalidTransmissionWords','_LinkFailures',
                           '_LossOfSignalCounter','_LossOfSyncCounter',
                           '_PrimitiveSequenceProtocolErrCount') {
             $hm->thresholdEvent($report, $orep, uc($type), $comp, $el, $shortid, $id, $wwn, 
                   {display_comp => $display } );
	   }
	}
     }
  }

  if (exists $rep->{FC_COUNTERS}) {
    $hm->fcEvent($rep->{FC_COUNTERS}, $orep->{FC_COUNTERS});
  }

  my $lists = $hm->component_lists();

  foreach my $label (keys %$lists) {
      my $val = $lists->{$label};
      my $report_names = $val->[0];
      my $tag_name     = $val->[1];

      my($INSERTS, $DELETES, $UPDATES) = $hm->idu_map($rep, $orep, $report_names, $tag_name);

      foreach my $el (keys %$DELETES) {
        my $comp = $DELETES->{$el};                       # el is the _Realizes value (vendor.part#.serial#)
        my $oserial = NWS::COMMON->getKey($orep, $comp);  # ctrl.1
        my $nws_module = $hm->NWS_module();
        my $class   = $nws_module->cimClass($comp);
        
	# Since it is removed, it would be a good idea to get the component from
	# the old report.
        Grid->setCode("$type.ComponentRemoveEvent." . $hm->code($comp, $orep));
   
        my $arg = { display_comp => $orep->get("$comp._ElementName") };
        $arg->{logicalDevice} = 1 if (!exists $orep->{"$comp._Realized"});
   
        $hm->removeCompEvent($comp,$physicalFrame, $report, $orep, $class , 
                             $oserial, $wwn, $arg);
     }
   
     foreach my $el (keys %$INSERTS) {
        my $comp = $INSERTS->{$el}; # el is the _Realizes value (vendor.part#.serial#)
   
        my $nserial = NWS::COMMON->getKey($rep, $comp);  # ctrl.1
        my $ctrl    = NWS::COMMON->insert($rep, $comp, $nwssystem, $physicalFrame);
   
        Grid->setCode("$type.ComponentInsertEvent."  . $hm->code($comp, $rep));
   
        my $arg = { display_comp => $rep->get("$comp._ElementName") };
        $arg->{logicalDevice} = 1 if (!exists $rep->{"$comp._Realized"});
   
        $hm->insertCompEvent($comp, $physicalFrame, $report, $orep, 
                                 $ctrl, $nserial, $wwn, $arg);
     }
   
     my $newFRUMAP = COMMON->fruMap($rep);
     my $oldFRUMAP = COMMON->fruMap($orep);
     
     foreach my $comp (keys %$UPDATES) { # $UPDATES->{new_index} => $old_index
        my $oserial = NWS::COMMON->getKey($orep, $comp);  # ctrl.2
        my $old_comp = $UPDATES->{$comp};                 # ctrl.1 (can be different)

        my $nws_module = $hm->NWS_module();
        my $class   = $nws_module->cimClass($comp);
   
        Grid->setCode("$type.StateChangeEvent." . $hm->code($comp, $rep));
   
        my $arg = { display_comp => $rep->get("$comp._ElementName"),
                    old_comp     => $old_comp };
        $arg->{logicalDevice} = 1 if (!exists $orep->{"$comp._Realized"});
   
        $hm->stateChangeEvent($comp, 'status', $report, $rep, $orep, $class, $oserial, 
                              $wwn, $arg);
   
        
        $hm->check_rev($orep, $rep, $report, $wwn, $id, $comp, $newFRUMAP, $oldFRUMAP);
      }
  }

  $hm->EXTRA_LOGIC($wwn, $id, $rep, $orep, $report);

}

sub code {
  my($class, $comp, $rep) = @_;
  my $code = $rep->{"$comp._Caption"};
  $code =~ s/\s+//g;
  return $code;
}


#  comp = disk.1
# ocomp = disk.2
# $newMap{$rep-> {$comp._Realized}}{_Firmware} = ..
# $oldMap{$orep->{$comp._Realized}}{_Firmware} = ..

sub check_rev {
  my($hm, $orep, $rep, $report, $wwn, $id, $comp, $newMap, $oldMap) = @_;

  next if (!exists $rep->{"$comp._Realized"});
  my $serial  = $rep->{"$comp._Realized"};
  my $display = $rep->{"$comp._ElementName"};

  my $rev  = $newMap->{$serial}{fwRev};
  my $orev = $oldMap->{$serial}{fwRev};

  my $cat   = $report->id('category');
  my $LB = Labels->read("CommonDesc");
  my($desc, $descE) = $LB->expand2(revision => "$display($serial)",
                                       "$cat $id", "'$orev'", "'$rev'");

  if ($rev && $orev && ($rev ne $orev) ) {
     Grid->setCode("$cat.AlarmEvent.revision");
     $hm->valueChangeEvent($comp, "", $report, $wwn, $desc, 1, "revision", 
          { display_comp => $display, descE => $descE } );
  }
}

sub status {
   my($hm, $rep, $orep, $comp0, $old_comp) = @_;
   my $cat   = $rep->get("id.device_type");
   $old_comp = $comp0 if (!$old_comp);

   my($comp, $rest) = split(/\./, $comp0);
   my $map = PDM->getDeviceStateMap("$cat.availability");

   my $status  =  $rep->getState("$comp0._RawStatus");
   my $ostatus = $orep->getState("$old_comp._RawStatus");

   my $common_status  =  $rep->getState("$comp0._Status");
   my $common_ostatus = $orep->getState("$old_comp._Status");

   my($old, $new, $sev, $act) = $map->transition("${comp}Status.$ostatus",
                                       "${comp}Status.$status", $orep, $rep);

   return ($ostatus, $status, $old, $new, $sev, $act, $common_ostatus, $common_status);
}

# Returns an  array of component types that have internal fibre ports.
# That is ports that are on the internal loop.  This general implementation
# returns an empty array.  It is meant to be overridden if there is internal
# port information for this device.

sub internal_port_components {

  return []
}
  

1;
