package Agent::JAVA_Parent;
#<copyright>
# ----------------------------------------------------------
# Sun Proprietary/Confidential Code
# Copyright 2004, Sun Microsystems, Inc. All rights reserved.
# ----------------------------------------------------------
#</copyright>
# $Id: JAVA_Parent.pm,v 1.24 2005/03/17 15:49:36 jkremer Exp $

use strict;
use Java::Report;
use Agent;
use base 'Agent';
use RasDB;

sub revision { '$Revision: 1.24 $ '}

# Subclasses must override these to define type and category.

# sub isSelectable { "Device type name"}
sub devType { "java_parent"}
sub category { "storage" }


#############################################################################
# sub RUN
# called by the framework multiple times, with different lists of devices
# to do.
# $static_list: lists of devices to do in this run.
# $pass : which pass is this.
#############################################################################
sub RUN {
  my($agent, $static_list, $pass) = @_;
  my ($timelapse, $dc);
  my($renv) = System->get_renv();
  $DB::single = 1;
  my $processed_list = [];
  my $locks = System->get_se_conflict();

  my($report, $dev);

  foreach $dev ( $agent->deviceList($static_list) ) {
    next if ($dev->{active} eq "N");

    if ($locks && index(",$locks,", ",$dev->{name},") >= 0 ) {
       Debug->print2( "-> $dev->{type}: skipping $dev->{name}, detected device lockfile");
       next;
    }

    $dc++;

    # CALL INSTRUMENTATION with one device from the deviceList config file.
    # $sys_report is a hash
    my $sys_report = $agent->INSTRUMENTATION($dev);
    my $warn_lines = $agent->MESSAGELOG($dev);
    if ($warn_lines) {
    	my $id = {
    		 deviceName  =>  $dev->{key},
    		 active      => "Y",
    		 display     => $dev->{name},
    		 name        => $dev->{name},
    		 class       => $dev->{class},
    		 category    => $dev->{type} . "message",
    		 ip          => $dev->{ip}
    		};
    	$report->{"id.name"} = $dev->{name};
    	my $new_rep = Report->new($id, $report , $warn_lines, Report::STATUS_OK);
    	require Health::Message;
    	Health::Message->all_logic($new_rep);
    	PDM->saveReport( $new_rep );
    }

    my $wwn = $dev->{key};
    my $connect_errs = $sys_report->{"rc.error"};

    # SAVE EVENT POINTER.
    my $problems = PDM->get_last_event();

    # CREATE A REPORT HEADER with identification for this report.
    my $agentClass = $agent->category() . "." . $agent->devType();
    my $report_header = {
			 deviceName => $wwn,
			 active     => $dev->{active},
			 class      => $agentClass,
			 name       => $dev->{name},
			 display    => $dev->{name},
			 category   => $agent->devType(),
			 ip         => $dev->{ipno},
			};
    $sys_report = {} if (!$sys_report);
    $agent->copyDev($dev, $sys_report);
    my $new_rep;
    if ($connect_errs) {
      $new_rep = Report->new($report_header, $sys_report, undef,
			     Report::STATUS_CANNOT_CONNECT );
    } else {
      Discover->updateTopoDevice($dev, {report => $sys_report});
      Agent->setIdSection($sys_report, $dev->{name},
			  $dev->{mgmtLevel}, $dev->{ip}, $dev->{ipno}, 
			  $dev->{key});
      $new_rep = Report->new($report_header, $sys_report);
    }

    # CALL HEALTH MODULE, generate EVENTS
    my $dev_type = uc($agent->devType());
    require "Health/$dev_type.pm";
    my $health_module = "Health::$dev_type";
    $health_module->LOGIC($new_rep);

    # SAVE INSTRUMENTATION REPORT
    PDM->saveReport($new_rep);

    # ABORT THE INSTRUMENTATION LOOP if a problem was found.
    my ($broke, $abort) = $agent->new_events($problems, $dev, 1);
    push(@$processed_list, $dev);
    last if ($broke && $pass == 1 || $abort);
  }

  # ALWAYS END RUN by returning a list of processed devices.
  return $processed_list;
}



######################################################################
# sub DISCOVERY: Discover a device given search properties.
# This method uses the java agent framework to probe for the device type.
#
# INPUT: Discovery search properties.
# OUTPUT: an array of hashes with each has having disovered properties.
sub DISCOVERY {
   my($class, $q) = @_;

   my $devType = $class->devType();
   my $category = $class->category();
   my @D;

   require Java::Discovery;
	return Java::Discovery->deviceSearch($q, $devType);
}


#####################################################################
# sub INSTRUMENTATION
# this function returns a hash with the instrumentation data obtained
# from the Java framework.
#
# INPUT : a config_device
# OUTPUT: a hash with device_specific data and
# 'rc.error' => "Probing error"
# 'rc.key' => "key of the device as found by the probe'
#
#####################################################################
sub INSTRUMENTATION {
  my($agent, $device) = @_;
  my(@s, %dev, $in, %info);
  my $renv = System->get_renv();
  return Report->readTest($device) if (System->get_testMode());

  my $devType = $device->{type};

  require Java::Report;
  my $R = Java::Report->instrument($device);

  # ADD Site Identification data to the report
  $agent->addIdentification($R);

  # ADD 'rc.key' to the report
  $R->{'rc.key'} = $R->{"id.wwn"};
  Timelapse->stopDev( $device);

  # RETURN a pointer to the HASH
  return $R;
}

sub MESSAGELOG {
  my($agent, $device) = @_;
  my $type   = $device->{type};
  my $key    = $device->{key};
  my $name   = $device->{name};
  my $ipno   = $device->{ipno};
  my $devKey = "$type:$key";
  my $renv   = System->get_renv();
  my (@err, $l);
  my ($index, @lines, $dev, $marker, $msgList);

  my $LOGName = "messages." . $agent->devType();
  my $LOGFile = $renv->{"$LOGName"} || "/var/adm/$LOGName";

  if (System->get_testMode()) {
     # READ FROM messages.<type>
     open(O, $LOGFile);
     while ($l = <O>) {
       chop($l);
       push(@lines, $l);
     }
     close(O);

  } else {
    # READ LOGS FROM DEVICE, SAVE TO messages.<type>
    use DevDB;
    $dev = DevDB->read($devKey);
    $marker = $dev->{log_file_marker};
	 if (!$marker){
		
	 }
    $msgList = Java::Report->message($marker, $device);
	 my $msgs = $msgList->{messages};
		
#	 if ($msgs){
#		open(O, ">>$LOGFile");
#		for($index = 0; $index <= $#$msgs; $index++) {
#		  my $msg = $msgs->[$index];
#		  my $L = "$msg->{line}";
#		  push(@lines, $L);
#		  print O "$L\n";
#		}
#		close(O);
#	 }
  }

  # PROCESS LOG ENTRIES, COMING FROM EITHER THE DEVICE OR messages.log
  # Log line format:
  # MMM dd HH:mm:ss device component: [ID 101] ERROR: Description
  my $policies = Policies->new($type . "_policies");
  for ($index = 0; $index <= $#lines; $index++ ) {
	 my $line = $lines[$index];
    my ($mo, $day, $time, $dev, $comp, $ID, $id) = split(/ /, $line);
	 my $cindex = rindex($comp, ":");
	 my $component;
	 if ($cindex > 0){
		$component = substr($comp, 0, $cindex);
	 }
	 my $compKey   = $devKey;
	 if ($component){
		$compKey = "$devKey:$component";
	 }
	 $policies->run(\@err, \@lines, \$index,
		 $component, $name, $compKey, $ipno, $devKey, 1);
  }

  if (!System->get_testMode()) {
    # SAVE MARKER IF NOT IN TEST-MODE
	 if ($msgList->{marker}){
		$dev->{log_file_marker} = $msgList->{marker};
		DevDB->write($devKey, $dev);
	 }
  }

  return (\@err);
}

#
# Create a hash of hashes for each report component.
#
sub makeReportTree {
  my($class, $rep) = @_;
  my %R;

  foreach my $e (keys %$rep) {
    my $ix  = rindex($e, '.');
    my $fru = substr($e, 0, $ix);
    my $var = substr($e, $ix+1);

    my $fruMap = $R{$fru};
    if (!$fruMap){
      my $fruHashMap = { $var => $rep->{$e} };
      $R{$fru} = $fruHashMap;
    }
    else {
      $fruMap->{$var}= $rep->{$e};
    }
  }
  return \%R;
}



####################################################################
#
# sub FRUS
# this function returns a standard data-structure for any device
# INPUT : the Instrumentation Report (lib/Report.pm)
# the device name
# OUTPUT: a pointer to a table of frus with one run per fru.
# [
# [ "name", "device_type", "FruType", "FruId",
# "Vendor", "Model", "Serial", "Revision", "Status" ],
# [ "name", "device_type", "FruType", "FruId",
# ]
####################################################################
sub FRUS {
  my($class, $r, $name) = @_;

  my(@F);
  my $devtype = $r->category();
  if (!-f System->get_home() . "/lib/DeviceReport/$devtype.pm") {
    return [];
  }
  require "DeviceReport/$devtype.pm";

  my $pk = "DeviceReport::$devtype";

  my $R = $pk->hash($r);
  my $FRUS = $R->{FRU};


  foreach my $id (keys %$FRUS) {
    my $fru = $FRUS->{$id};
    push(@F, [$name, $devtype, $fru->{type},
		 $fru->{name},
		 $fru->{vendor},
		 $fru->{model},
		 $fru->{serial},
		 $fru->{revision},
              ]);
  }

  return \@F;
}


####################################################################
# sub REPORT: returns html used in GUI to display device Report.
#
# Since the Java framework will use Standard Reports this is all that
# needs to be done.
####################################################################
use DeviceReport;
sub REPORT {
  my($class, $host, $r, $arg) = @_;
  return if (!$r);

  DeviceReport->standardReport($r, {
       skipSections => "diskExtent",
       skipColumns  => "unit.\$caption,disk.\$caption,ctrl.\$caption",
      }
  );
}

1;
