
#
# This perl script searches the specified fixed-length record ascii
# database for records between $searchStartDate and $searchEndDate.  
# For each record between these dates, in then checks the record
# contents against the search criteria, and outputs it if it matches.
#

$searchStartDate = $ARGV[0]; 
$searchEndDate   = $ARGV[1]; 
$interfaces      = $ARGV[2]; 
$types           = $ARGV[3]; 
$types_negate    = $ARGV[4]; 
$users           = $ARGV[5]; 
$users_negate    = $ARGV[6]; 
$totalsOnly      = $ARGV[7]; 

$fileName        = "$ENV{SERVER_VAR}/databases/master"; 
$recordSize      = 200;
$offsetToDate    = 10;
$dateLength      = 10;
$first           = 0;
$last            = 1;

unless ($searchStartDate =~ /\d+\/\d+\/\d+/) {
  print "usage: <start date> <end date> (in mm/dd/yyyy format)\n";
  exit(1);
}
unless ($searchEndDate =~ /\d+\/\d+\/\d+/) {
  print "usage: <start date> <end date> (in mm/dd/yyyy format)\n";
  exit(1);
}

#
# Open database
#

open(handle, $fileName); 

#
# Get size of file, and then number of records
#

($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
 $atime,$mtime,$ctime,$blksize,$blocks) = stat($fileName);
$numRecords = $size/$recordSize;

#
# Binary search for first record >= $searchStartDate
#

$startRecord = &search(1,$numRecords,$searchStartDate,$first);

#
# Binary search for last record <= $searchStartDate
#

$endRecord   = &search(1,$numRecords,$searchEndDate,$last);

#
# Traverse range of records to compile stats.
#

if (!$totalsOnly) {
#  printf("%8s %10s %10s %20s %40s %40s %25s\n", "Job#", "Date", "Interface", "Solver", "From Address", "Forward Address", "Warnings");
#  printf("%8s %10s %10s %20s %40s %40s %25s\n", "----", "----", "---------", "------", "------------", "---------------", "--------");
    write _TOP;
} 

$total = 0;
if (($startRecord != -1)&&($endRecord!=-1)) {
  for ($i=$startRecord;$i<=$endRecord;$i++) {
    seek(handle, ($i-1)*$recordSize, 0);
    read(handle, $record, $recordSize);
    ($number, $startDate, $startTime, $endDate, $endTime, $interface, $type, $address, $forward, $warnings) = unpack("A10 A10 A8 A10 A8 A16 A30 A50 A50 A7", $record);
    if ($interface =~ /$interfaces/) {
      if (($type =~ /$types/)xor($types_negate)) {
        $addresses = "$address $forward";
        if (($addresses =~ /$users/)xor($users_negate)) {
          $total++;
          if (!$totalsOnly) {
	      $warnings =~ s/^\s+//;
	      $warnings =~ s/\s+$//;
#	      printf("%8s %10s %10s %20s %40s %40s %25s\n", $number, $startDate, $interface, $type, $address, $forward, $warnings);
	      write;
	  } else {
            if ($totalsOnly == 2) {
              unless ($address =~ /WEB_USER|TRIAL_WEB_USER/) {
                unless ($DISPLAYED{$address}) {
                  printf("$address\n");
                  $DISPLAYED{$address} = 1;
                }
              }
              if ($forward =~ /\S+/) {
                unless ($DISPLAYED{$foward}) {
                  printf("$forward\n");
                  $DISPLAYED{$forward} = 1;
                }
              }
            }
          }
        }
      }
    }
  }
}

print "\n$total matching records\n";


#
# sub to compare two dates. -1 = less, 0 = equal, 1 = greater
#

sub dateCompare {
  $_[0] =~ /(\d+)\/(\d+)\/(\d+)/;
  $m1 = $1; $d1 = $2; $y1 = $3;
  $_[1] =~ /(\d+)\/(\d+)\/(\d+)/;
  $m2 = $1; $d2 = $2; $y2 = $3;

  if ($y2 > $y1) {
    return -1;
  }
  if ($y2 < $y1) {
    return 1;
  }
  if ($m2 > $m1) {
    return -1;
  }
  if ($m2 < $m1) {
    return 1;
  }
  if ($d2 > $d1) {
    return -1;
  }
  if ($d2 < $d1) {
    return 1;
  }
  return 0;
}

#
# Binary search subroutine
#

sub search {
  local($p,$r,$v,$pdate,$qdate,$last,$compare);
 
  $p    = $_[0];
  $r    = $_[1];
  $v    = $_[2]; 
  $last = $_[3];

  if ($p == $r) {
    $pdate = getStartDateFromRecord($p);
    $compare = &dateCompare($pdate,$v);
    if ($last) {
      if ($compare == 1) {
        return -1;
      } else {
        return $p;
      }
    } else {
      if ($compare == -1) {
        return -1;
      } else {
        return $p;
      }
    }
  }
  if ($last) {
    $q = int(($p+$r)/2+0.5);
  } else {
    $q = int(($p+$r)/2);
  } 
  $qdate = getStartDateFromRecord($q);
  $compare = &dateCompare($qdate,$v);
  if ($last) {
    $rightTest = ($compare != 1);
  } else {
    $rightTest = ($compare == -1);
  }
  if ($last) {
    if ($rightTest) {
      return &search($q, $r, $v, $last);
    } else {
      return &search($p, $q-1, $v, $last);
    }
  } else {
    if ($rightTest) {
      return &search($q+1, $r, $v, $last);
    } else {
      return &search($p, $q, $v, $last);
    }
  }
}

sub getStartDateFromRecord {
  local($startDate); 
  $i = $_[0];
  seek(handle, ($i-1)*$recordSize+$offsetToDate, 0);
  read(handle, $startDate, $dateLength);
  return $startDate;
}

sub getDomainExtension {
    local($domainExt) = $_[0];
    $domainExt =~ s/.*\.//g;
    $domainExt = "ip address" if ($domainExt =~ /[0-9].*/);
    $domainExt =~ tr/[A-Z]/[a-z]/;
    return $domainExt;
}

sub DescribeDomain {
    local($description) = "Unknown"; # Default domain description
    local($domain) = $_[0];          # Domain extension (passed parameter)
    $domaincodes = "$ENV{SERVER_HOME}/server/lib/domain.desc";

    if ($domain ne "ip address") {
        if (!(keys %domainDesc)) {
            open (CODES, "<$domaincodes") || die "Couldn't open $domaincodes\n";
            while (<CODES>) {
                    chomp;
                    ($code, $description) = split('   ');
                    $code =~ tr/[A-Z]/[a-z]/;
                    $domainDesc{$code} = $description;
            }
            close(CODES);
        }
        if ($domainDesc{$domain}) {
            $description = $domainDesc{$domain};
        }
    }
    return $description;
}

format _TOP = 
  Job#      Date    Interface         Solver        From Address                             Forward Address                          Warnings
-------- ---------- ---------- -------------------- ---------------------------------------- ---------------------------------------- -------------------------
.

format = 
@>>>>>>> @<<<<<<<<< @||||||||| @<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<
$number, $startDate, $interface, $type,             $address, $forward, $warnings
.
