Last batch of updates
[clearscm.git] / clearadm / lib / Clearadm.pm
index fb63079..1f74aaf 100644 (file)
@@ -36,9 +36,9 @@ specifics about the method you are envoking.
 
  # Create new Clearadm object
  my $clearadm = new Clearadm;
+
  # Add a new system
- my %system = (
+ my %system =(
   name          => 'jupiter',
   alias         => 'defaria.com',
   admin         => 'Andrew DeFaria',
@@ -46,31 +46,31 @@ specifics about the method you are envoking.
   type          => 'Linux',
   description   => 'Home server',
  );
- my ($err, $msg) = $clearadm->AddSystem (%system);
+
+ my ($err, $msg) = $clearadm->AddSystem(%system);
+
  # Find systems matching 'jup'
- my @systems = $clearadm->FindSystem ('jup');
+ my @systems = $clearadm->FindSystem('jup');
+
  # Get a system by name
- my %system = $clearadm->GetSystem ('jupiter');
+ my %system = $clearadm->GetSystem('jupiter');
+
  # Update system
  my %update = (
   'region' => 'East Coast',
  );
 
  my ($err, $msg) = $clearadm->UpdateSystem ('jupiter', %update);
+
  # Delete system (Warning: will delete all related records regarding this
  # system).
- my ($err, $msg) = $clearadm->DeleteSystem ('jupiter');
+ my ($err, $msg) = $clearadm->DeleteSystem('jupiter');
 
 =head1 DESCRIPTION
 
 This package provides and object oriented interface to the Clearadm database.
-Methods are provided to manipulate records by adding, updating and deleting 
-them. In general you need to specify a hash which contains keys and values 
+Methods are provided to manipulate records by adding, updating and deleting
+them. In general you need to specify a hash which contains keys and values
 corresponding to the database field names and values.
 
 =head1 ROUTINES
@@ -88,6 +88,7 @@ use Carp;
 use DBI;
 use File::Basename;
 use Net::Domain qw(hostdomain);
+use Sys::Hostname;
 
 use FindBin;
 
@@ -97,27 +98,29 @@ use DateUtils;
 use Display;
 use GetConfig;
 use Mail;
+use Clearcase::Vob;
+use Clearcase::View;
 
-my $conf = dirname (__FILE__) . '/../etc/clearadm.conf';
+my $conf = dirname(__FILE__) . '/../etc/clearadm.conf';
 
-our %CLEAROPTS = GetConfig ($conf);
+our %CLEAROPTS = GetConfig($conf);
 
 # Globals
 our $VERSION  = '$Revision: 1.54 $';
    ($VERSION) = ($VERSION =~ /\$Revision: (.*) /);
-  
-$CLEAROPTS{CLEARADM_USERNAME} = $ENV{CLEARADM_USERNAME} 
+
+$CLEAROPTS{CLEARADM_USERNAME} = $ENV{CLEARADM_USERNAME}
                               ? $ENV{CLEARADM_USERNAME}
                               : $CLEAROPTS{CLEARADM_USERNAME}
                               ? $CLEAROPTS{CLEARADM_USERNAME}
                               : 'clearwriter';
-$CLEAROPTS{CLEARADM_PASSWORD} = $ENV{CLEARADM_PASSWORD} 
+$CLEAROPTS{CLEARADM_PASSWORD} = $ENV{CLEARADM_PASSWORD}
                               ? $ENV{CLEARADM_PASSWORD}
                               : $CLEAROPTS{CLEARADM_PASSWORD}
                               ? $CLEAROPTS{CLEARADM_PASSWORD}
                               : 'clearwriter';
-$CLEAROPTS{CLEARADM_SERVER}   = $ENV{CLEARADM_SERVER} 
-                              ? $ENV{CLEARADM_SERVER} 
+$CLEAROPTS{CLEARADM_SERVER}   = $ENV{CLEARADM_SERVER}
+                              ? $ENV{CLEARADM_SERVER}
                               : $CLEAROPTS{CLEARADM_SERVER}
                               ? $CLEAROPTS{CLEARADM_SERVER}
                               : 'localhost';
@@ -127,152 +130,149 @@ my $defaultFilesystemHist      = '6 months';
 my $defaultLoadavgHist         = '6 months';
 
 # Internal methods
-sub _dberror ($$) {
+sub _dberror($$) {
   my ($self, $msg, $statement) = @_;
 
   my $dberr    = $self->{db}->err;
   my $dberrmsg = $self->{db}->errstr;
-  
+
   $dberr    ||= 0;
   $dberrmsg ||= 'Success';
 
   my $message = '';
-  
+
   if ($dberr) {
-    my $function = (caller (1)) [3];
+    my $function = (caller(1)) [3];
 
     $message = "$function: $msg\nError #$dberr: $dberrmsg\n"
              . "SQL Statement: $statement";
   } # if
 
-  return $dberr, $message;  
+  return $dberr, $message;
 } # _dberror
 
-sub _formatValues (@) {
+sub _formatValues(@) {
   my ($self, @values) = @_;
-  
+
   my @returnValues;
-  
+
   # Quote data values
-  push @returnValues, $_ eq '' ? 'null' : $self->{db}->quote ($_)  
-    foreach (@values);
-  
+  push @returnValues, $_ eq '' ? 'null' : $self->{db}->quote($_) for (@values);
+
   return @returnValues;
 } # _formatValues
 
-sub _formatNameValues (%) {
+sub _formatNameValues(%) {
   my ($self, %rec) = @_;
-  
+
   my @nameValueStrs;
-  
-  push @nameValueStrs, "$_=" . $self->{db}->quote ($rec{$_})
-    foreach (keys %rec);
-    
+
+  push @nameValueStrs, "$_=" . $self->{db}->quote($rec{$_}) for (keys %rec);
+
   return @nameValueStrs;
 } # _formatNameValues
 
-sub _addRecord ($%) {
+sub _addRecord($%) {
   my ($self, $table, %rec) = @_;
-  
+
   my $statement  = "insert into $table (";
      $statement .= join ',', keys %rec;
      $statement .= ') values (';
-     $statement .= join ',', $self->_formatValues (values %rec);
+     $statement .= join ',', $self->_formatValues(values %rec);
      $statement .= ')';
-  
+
   my ($err, $msg);
-  
-  $self->{db}->do ($statement);
-  
-  return $self->_dberror ("Unable to add record to $table", $statement);
+
+  $self->{db}->do($statement);
+
+  return $self->_dberror("Unable to add record to $table", $statement);
 } # _addRecord
 
-sub _deleteRecord ($;$) {
+sub _deleteRecord($;$) {
   my ($self, $table, $condition) = @_;
-  
+
   my $count;
-  
+
   my $statement  = "select count(*) from $table ";
-     $statement .= "where $condition"
-      if $condition;
-  
-  my $sth = $self->{db}->prepare ($statement)
-    or return $self->_dberror ('Unable to prepare statement', $statement);
-    
+     $statement .= "where $condition" if $condition;
+
+  my $sth = $self->{db}->prepare($statement)
+    or return $self->_dberror('Unable to prepare statement', $statement);
+
   $sth->execute
-    or return $self->_dberror ('Unable to execute statement', $statement);
-    
+    or return $self->_dberror('Unable to execute statement', $statement);
+
   my @row = $sth->fetchrow_array;
-  
+
   $sth->finish;
-  
+
   if ($row[0]) {
     $count = $row[0];
   } else {
     $count = 0;
   } # if
-  
-  return ($count, 'Records deleted')
-    if $count == 0;
-    
+
+  return ($count, 'Records deleted') if $count == 0;
+
   $statement  = "delete from $table ";
-  $statement .= "where $condition"
-    if $condition;
-  
-  $self->{db}->do ($statement);
-  
+  $statement .= "where $condition" if $condition;
+
+  $self->{db}->do($statement);
+
   if ($self->{db}->err) {
-    return $self->_dberror ("Unable to delete record from $table", $statement);
+    return $self->_dberror("Unable to delete record from $table", $statement);
   } else {
     return $count, 'Records deleted';
   } # if
 } # _deleteRecord
 
-sub _updateRecord ($$%) {
+sub _updateRecord($$%) {
   my ($self, $table, $condition, %rec) = @_;
 
   my $statement  = "update $table set ";
-     $statement .= join ',', $self->_formatNameValues (%rec);
-     $statement .= " where $condition"
-       if $condition;
-  
-  $self->{db}->do ($statement);
-  
-  return $self->_dberror ("Unable to update record in $table", $statement);
+     $statement .= join ',', $self->_formatNameValues(%rec);
+     $statement .= " where $condition" if $condition;
+
+  $self->{db}->do($statement);
+
+  return $self->_dberror("Unable to update record in $table", $statement);
 } # _updateRecord
 
-sub _checkRequiredFields ($$) {
+sub _checkRequiredFields($$) {
   my ($fields, $rec) = @_;
-  
-  foreach my $fieldname (@$fields) {
+
+  for my $fieldname (@$fields) {
     my $found = 0;
-    
-    foreach (keys %$rec) {
+
+    for (keys %$rec) {
       if ($fieldname eq $_) {
         $found = 1;
         last;
       } # if
-    } # foreach
-    
-    return "$fieldname is required"
-      unless $found;
-  } # foreach
-  
+    } # for
+
+    return "$fieldname is required" unless $found;
+  } # for
+
   return;
 } # _checkRequiredFields
 
-sub _getRecords ($$) {
-  my ($self, $table, $condition) = @_;
-  
+sub _getRecords($$;$) {
+  my ($self, $table, $condition, $additional) = @_;
+
   my ($err, $msg);
-    
-  my $statement = "select * from $table where $condition";
-  
-  my $sth = $self->{db}->prepare ($statement);
-  
+
+  $additional ||= '';
+
+  my $statement  = "select * from $table";
+     $statement .= " where $condition" if $condition;
+     $statement .= $additional;
+
+  my $sth = $self->{db}->prepare($statement);
+
   unless ($sth) {
-    ($err, $msg) = $self->_dberror ('Unable to prepare statement', $statement);
-    
+    ($err, $msg) = $self->_dberror('Unable to prepare statement', $statement);
+
     croak $msg;
   } # if
 
@@ -280,224 +280,222 @@ sub _getRecords ($$) {
   my $maxAttempts = 3;
   my $sleepTime   = 30;
   my $status;
-  
+
   # We've been having the server going away. Supposedly it should reconnect so
-  # here we simply retry up to $maxAttempts times to re-execute the statement. 
+  # here we simply retry up to $maxAttempts times to re-execute the statement.
   # (Are there other places where we need to do this?)
   $err = 2006;
-  
+
   while ($err == 2006 and $attempts++ < $maxAttempts) {
     $status = $sth->execute;
-    
+
     if ($status) {
       $err = 0;
       last;
     } else {
-      ($err, $msg) = $self->_dberror ('Unable to execute statement',
+      ($err, $msg) = $self->_dberror('Unable to execute statement',
                                       $statement);
     } # if
-    
+
     last if $err == 0;
-    
+
     croak $msg unless $err == 2006;
 
     my $timestamp = YMDHMS;
-      
-    $self->Error ("$timestamp: Unable to talk to DB server.\n\n$msg\n\n"
+
+    $self->Error("$timestamp: Unable to talk to DB server.\n\n$msg\n\n"
                 . "Will try again in $sleepTime seconds", -1);
-                
+
     # Try to reconnect
-    $self->_connect ($self->{dbserver});
+    $self->_connect($self->{dbserver});
 
     sleep $sleepTime;
   } # while
 
-  $self->Error ("After $maxAttempts attempts I could not connect to the database", $err)
+  $self->Error("After $maxAttempts attempts I could not connect to the database", $err)
     if ($err == 2006 and $attempts > $maxAttempts);
-  
+
   my @records;
-  
+
   while (my $row = $sth->fetchrow_hashref) {
     push @records, $row;
   } # while
-  
+
   return @records;
-} # _getRecord
+} # _getRecords
 
-sub _aliasSystem ($) {
+sub _aliasSystem($) {
   my ($self, $system) = @_;
-  
-  my %system = $self->GetSystem ($system);
-  
+
+  my %system = $self->GetSystem($system);
+
   if ($system{name}) {
     return $system{name};
   } else {
-       return;
+    return;
   } # if
 } # _aliasSystem
 
-sub _getLastID () {
+sub _getLastID() {
   my ($self) = @_;
-  
+
   my $statement = 'select last_insert_id()';
-  
-  my $sth = $self->{db}->prepare ($statement);
-  
+
+  my $sth = $self->{db}->prepare($statement);
+
   my ($err, $msg);
-  
+
   unless ($sth) {
-    ($err, $msg) = $self->_dberror ('Unable to prepare statement', $statement);
-    
+    ($err, $msg) = $self->_dberror('Unable to prepare statement', $statement);
+
     croak $msg;
   } # if
-    
+
   my $status = $sth->execute;
-  
+
   unless ($status) {
-    ($err, $msg) = $self->_dberror ('Unable to execute statement', $statement);
-    
+    ($err, $msg) = $self->_dberror('Unable to execute statement', $statement);
+
     croak $msg;
   } # if
-    
+
   my @records;
 
   my @row = $sth->fetchrow_array;
-  
+
   return $row[0];
 } # _getLastID
 
-sub _connect (;$) {
+sub _connect(;$) {
   my ($self, $dbserver) = @_;
-  
+
   $dbserver ||= $CLEAROPTS{CLEARADM_SERVER};
-  
+
   my $dbname   = 'clearadm';
   my $dbdriver = 'mysql';
 
-  $self->{db} = DBI->connect (
-    "DBI:$dbdriver:$dbname:$dbserver", 
+  $self->{db} = DBI->connect(
+    "DBI:$dbdriver:$dbname:$dbserver",
     $CLEAROPTS{CLEARADM_USERNAME},
     $CLEAROPTS{CLEARADM_PASSWORD},
     {PrintError => 0},
-  ) or croak (
-    "Couldn't connect to $dbname database " 
+  ) or croak(
+    "Couldn't connect to $dbname database "
   . "as $CLEAROPTS{CLEARADM_USERNAME}\@$CLEAROPTS{CLEARADM_SERVER}"
   );
-  
+
   $self->{dbserver} = $dbserver;
-  
+
   return;
 } # _connect
 
-sub new (;$) {
+sub new(;$) {
   my ($class, $dbserver) = @_;
 
   my $self = bless {}, $class;
 
-  $self->_connect ($dbserver);
+  $self->_connect($dbserver);
 
   return $self;
 } # new
 
-sub SetNotify () {
+sub SetNotify() {
   my ($self) = @_;
-  
+
   $self->{NOTIFY} = $CLEAROPTS{CLEARADM_NOTIFY};
-  
+
   return;
 } # SetNotify
 
-sub Error ($;$) {
+sub Error($;$) {
   my ($self, $msg, $errno) = @_;
 
   # If $errno is specified we need to stop. However we need to notify somebody
-  # that cleartasks is no longer running.  
+  # that cleartasks is no longer running.
   error $msg;
-  
+
   if ($errno) {
     if ($self->{NOTIFY}) {
-      mail (
+      mail(
         to      => $self->{NOTIFY},
         subject => 'Internal error occurred in Clearadm',
         data    => "<p>An unexpected, internal error occurred in Clearadm:</p><p>$msg</p>",
         mode    => 'html',
       );
-    
+
       exit $errno  if $errno > 0;
     } # if
   } # if
-  
+
   return;
 } # Error
 
-sub AddSystem (%) {
+sub AddSystem(%) {
   my ($self, %system) = @_;
-  
+
   my @requiredFields = (
     'name',
   );
 
   my $result = _checkRequiredFields \@requiredFields, \%system;
-  
-  return -1, "AddSystem: $result"
-    if $result;
-  
+
+  return -1, "AddSystem: $result" if $result;
+
   $system{loadavgHist} ||= $defaultLoadavgHist;
-  
-  return $self->_addRecord ('system', %system);
+
+  return $self->_addRecord('system', %system);
 } # AddSystem
 
-sub DeleteSystem ($) {
+sub DeleteSystem($) {
   my ($self, $name) = @_;
 
-  return $self->_deleteRecord ('system', "name='$name'");  
+  return $self->_deleteRecord('system', "name='$name'");
 } # DeleteSystem
 
 sub UpdateSystem ($%) {
   my ($self, $name, %update) = @_;
 
-  return $self->_updateRecord ('system', "name='$name'", %update);
+  return $self->_updateRecord('system', "name='$name'", %update);
 } # UpdateSystem
 
-sub GetSystem ($) {
+sub GetSystem($) {
   my ($self, $system) = @_;
-  
-  return
-    unless $system;
-  
-  my @records = $self->_getRecords (
-    'system', 
+
+  return unless $system;
+
+  my @records = $self->_getRecords(
+    'system',
     "name='$system' or alias like '%$system%'"
   );
-  
+
   if ($records[0]) {
     return %{$records[0]};
   } else {
-       return;
+    return;
   } # if
 } # GetSystem
 
-sub FindSystem (;$) {
+sub FindSystem(;$) {
   my ($self, $system) = @_;
 
   $system ||= '';
-  
+
   my $condition = "name like '%$system%' or alias like '%$system%'";
-                         
-  return $self->_getRecords ('system', $condition);
+
+  return $self->_getRecords('system', $condition);
 } # FindSystem
 
-sub SearchSystem (;$) {\r
+sub SearchSystem(;$) {\r
   my ($self, $condition) = @_;
-  
+
   $condition = "name like '%'" unless $condition;
-  
-  return $self->_getRecords ('system', $condition); \r
+
+  return $self->_getRecords('system', $condition);\r
 } # SearchSystem
 
-sub AddPackage (%) {
+sub AddPackage(%) {
   my ($self, %package) = @_;
-  
+
   my @requiredFields = (
     'system',
     'name',
@@ -505,73 +503,67 @@ sub AddPackage (%) {
   );
 
   my $result = _checkRequiredFields \@requiredFields, \%package;
-  
-  return -1, "AddPackage: $result"
-    if $result;
-  
-  return $self->_addRecord ('package', %package);
+
+  return -1, "AddPackage: $result" if $result;
+
+  return $self->_addRecord('package', %package);
 } # AddPackage
 
-sub DeletePackage ($$) {
+sub DeletePackage($$) {
   my ($self, $system, $name) = @_;
-  
-  return $self->_deleteRecord (
-    'package', 
+
+  return $self->_deleteRecord(
+    'package',
     "(system='$system' or alias='$system') and name='$name'");
 } # DeletePackage
 
-sub UpdatePackage ($$%) {
+sub UpdatePackage($$%) {
   my ($self, $system, $name, %update) = @_;
-  
-  $system = $self->_aliasSystem ($system);
-  
-  return
-    unless $system;
-    
-  return $self->_updateRecord ('package', "system='$system'", %update);
+
+  $system = $self->_aliasSystem($system);
+
+  return unless $system;
+
+  return $self->_updateRecord('package', "system='$system'", %update);
 } # UpdatePackage
 
 sub GetPackage($$) {
   my ($self, $system, $name) = @_;
-  
-  $system = $self->_aliasSystem ($system);
-  
-  return
-    unless $system;
-    
-  return
-    unless $name;
-    
-  my @records = $self->_getRecords (
-    'package', 
+
+  $system = $self->_aliasSystem($system);
+
+  return unless $system;
+  return unless $name;
+
+  my @records = $self->_getRecords(
+    'package',
     "system='$system' and name='$name'"
   );
-  
+
   if ($records[0]) {
     return %{$records[0]};
   } else {
-       return;
+    return;
   } # if
 } # GetPackage
 
-sub FindPackage ($;$) {
+sub FindPackage($;$) {
   my ($self, $system, $name) = @_;
 
   $name ||= '';
 
-  $system = $self->_aliasSystem ($system);
-  
-  return
-    unless $system;
-    
+  $system = $self->_aliasSystem($system);
+
+  return unless $system;
+
   my $condition = "system='$system' and name like '%$name%'";
-  
-  return $self->_getRecords ('package', $condition);
+
+  return $self->_getRecords('package', $condition);
 } # FindPackage
 
-sub AddFilesystem (%) {
+sub AddFilesystem(%) {
   my ($self, %filesystem) = @_;
-  
+
   my @requiredFields = (
     'system',
     'filesystem',
@@ -579,61 +571,55 @@ sub AddFilesystem (%) {
   );
 
   my $result = _checkRequiredFields \@requiredFields, \%filesystem;
-  
-  return -1, "AddFilesystem: $result"
-    if $result;
-    
+
+  return -1, "AddFilesystem: $result" if $result;
+
   # Default filesystem threshold
   $filesystem{threshold} ||= $defaultFilesystemThreshold;
-  
-  return $self->_addRecord ('filesystem', %filesystem);
+
+  return $self->_addRecord('filesystem', %filesystem);
 } # AddFilesystem
 
-sub DeleteFilesystem ($$) {
+sub DeleteFilesystem($$) {
   my ($self, $system, $filesystem) = @_;
-  
-  $system = $self->_aliasSystem ($system);
-  
-  return
-    unless $system;
-    
-  return $self->_deleteRecord (
-    'filesystem', 
+
+  $system = $self->_aliasSystem($system);
+
+  return unless $system;
+
+  return $self->_deleteRecord(
+    'filesystem',
     "system='$system' and filesystem='$filesystem'"
   );
 } # DeleteFilesystem
 
-sub UpdateFilesystem ($$%) {
+sub UpdateFilesystem($$%) {
   my ($self, $system, $filesystem, %update) = @_;
-  
-  $system = $self->_aliasSystem ($system);
-  
-  return
-    unless $system;
-    
-  return $self->_updateRecord (
+
+  $system = $self->_aliasSystem($system);
+
+  return unless $system;
+
+  return $self->_updateRecord(
     'filesystem',
     "system='$system' and filesystem='$filesystem'",
     %update
   );
 } # UpdateFilesystem
 
-sub GetFilesystem ($$) {
+sub GetFilesystem($$) {
   my ($self, $system, $filesystem) = @_;
-  
-  $system = $self->_aliasSystem ($system);
-  
-  return
-    unless $system;
-    
-  return
-    unless $filesystem;
-    
-  my @records = $self->_getRecords (
-    'filesystem', 
+
+  $system = $self->_aliasSystem($system);
+
+  return unless $system;
+  return unless $filesystem;
+
+  my @records = $self->_getRecords(
+    'filesystem',
     "system='$system' and filesystem='$filesystem'"
   );
-  
+
   if ($records[0]) {
     return %{$records[0]};
   } else {
@@ -641,156 +627,194 @@ sub GetFilesystem ($$) {
   } # if
 } # GetFilesystem
 
-sub FindFilesystem ($;$) {
+sub FindFilesystem($;$) {
   my ($self, $system, $filesystem) = @_;
-  
+
   $filesystem ||= '';
 
-  $system = $self->_aliasSystem ($system);
-  
-  return
-    unless $system;
+  $system = $self->_aliasSystem($system);
+
+  return unless $system;
 
-  my $condition = "system='$system' and filesystem like '%$filesystem%'";     
-      
-  return $self->_getRecords ('filesystem', $condition);
+  my $condition = "system='$system' and filesystem like '%$filesystem%'";
+
+  return $self->_getRecords('filesystem', $condition);
 } # FindFilesystem
 
-sub AddVob (%) {
+sub AddVob(%) {
   my ($self, %vob) = @_;
-  
+
   my @requiredFields = (
-    'system',
     'tag',
+    'region',
   );
 
   my $result = _checkRequiredFields \@requiredFields, \%vob;
-  
-  return -1, "AddVob: $result"
-    if $result;
-  
-  return $self->_addRecord ('vob', %vob);
+
+  return -1, "AddVob: $result" if $result;
+
+  return $self->_addRecord('vob', %vob);
 } # AddVob
 
-sub DeleteVob ($) {
-  my ($self, $tag) = @_;
-  
-  return $self->_deleteRecord ('vob', "tag='$tag'");
+sub DeleteVob($$) {
+  my ($self, $tag, $region) = @_;
+
+  return $self->_deleteRecord('vob', "tag='$tag' and region='$region'");
 } # DeleteVob
 
-sub GetVob ($) {
-  my ($self, $tag) = @_;
-  
-  return 
-    unless $tag;
-    
-  my @records = $self->_getRecords ('vob', "tag='$tag'");
-  
+sub GetVob($$) {
+  my ($self, $tag, $region) = @_;
+
+  return unless $tag;
+
+  # Windows vob tags begin with "\", which is problematic. The solution is to
+  # escape the "\"
+  $tag =~ s/^\\/\\\\/;
+
+  my @records = $self->_getRecords('vob', "tag='$tag' and region='$region'");
+
   if ($records[0]) {
     return %{$records[0]};
   } else {
-       return;
+    return;
   } # if
 } # GetVob
 
-sub FindVob ($) {
-  my ($self, $tag) = @_;
+sub FindVobStorage(;$$) {
+  my ($self, $tag, $region) = @_;
+
+  $tag    ||= '';
+  $region ||= '';
+
+  # Windows vob tags begin with "\", which is problematic. The solution is to
+  # escape the "\"
+  $tag =~ s/^\\/\\\\/;
+
+  my $condition = "tag like '%$tag%'";
+  
+  $condition .= " and region='$region'" if $region;
+
+  return $self->_getRecords('vobstorage', $condition);
+} # FindVobStorage
+
+sub FindVob(;$$) {
+  my ($self, $tag, $region) = @_;
+
+  $tag    ||= '';
+  $region ||= '';
+
+  # Windows vob tags begin with "\", which is problematic. The solution is to
+  # escape the "\"
+  $tag =~ s/^\\/\\\\/;
+
+  my $condition = "tag like '%$tag%'";
   
-  return $self->_getRecords ('vob', "tag like '%$tag%'");
+  $condition .= " and region='$region'" if $region;
+
+  return $self->_getRecords('vob', $condition);
 } # FindVob
 
-sub AddView (%) {
+sub UpdateVob(%) {
+  my ($self, %vob) = @_;
+
+  # Windows vob tags begin with "\", which is problematic. The solution is to
+  # escape the "\"
+  my $vobtag = $vob{tag};
+
+  $vobtag =~ s/^\\/\\\\/;
+
+  return $self->_updateRecord('vob', "tag='$vobtag' and region='$vob{region}'", %vob);
+} # UpdateVob
+
+sub AddView(%) {
   my ($self, %view) = @_;
-  
+
   my @requiredFields = (
-    'system',
     'tag',
+    'region'
   );
 
   my $result = _checkRequiredFields \@requiredFields, \%view;
-  
-  return -1, "AddView: $result"
-    if $result;
-  
-  return $self->_addRecord ('view', %view);
-} # AddView
 
-sub DeleteView ($) {
-  my ($self, $tag) = @_;
-  
-  return $self->_deleteRecord ('vob', "tag='$tag'");
+  return -1, "AddView: $result" if $result;
+
+  return $self->_addRecord('view', %view);
+} # AddView
+
+sub DeleteView($$) {
+  my ($self, $tag, $region) = @_;
+
+  return $self->_deleteRecord('vob', "tag='$tag' and region='$region'");
 } # DeleteView
 
-sub GetView ($) {
-  my ($self, $tag) = @_;
-  
-  return
-    unless $tag;
-  
-  my @records = $self->_getRecords ('view', "tag='$tag'");
-  
+sub UpdateView(%) {
+  my ($self, %view) = @_;
+
+  return $self->_updateRecord('view', "tag='$view{tag}' and region='$view{region}'", %view);
+} # UpdateView
+
+sub GetView($$) {
+  my ($self, $tag, $region) = @_;
+
+  return unless $tag;
+
+  my @records = $self->_getRecords('view', "tag='$tag' and region='$region'");
+
   if ($records[0]) {
     return %{$records[0]};
   } else {
-       return;
+    return;
   } # if
 } # GetView
 
-sub FindView (;$$$$) {
-  my ($self, $system, $region, $tag, $ownerName) = @_;
+sub FindView(;$$$$) {
+  my ($self, $tag, $region, $ownerName) = @_;
 
-  $system    ||= '';
-  $region    ||= '';
-  $tag       ||= '';
-  $ownerName ||= '';
-  
   my $condition;
-  
-  $condition  = "system like '%$system%'";
-  $condition .= ' and ';
-  $condition  = "region like '%$region%'";
-  $condition .= ' and ';
-  $condition .= "tag like '%$tag'";
-  $condition .= ' and ';
-  $condition .= "ownerName like '%$ownerName'";
-                         
-  return $self->_getRecords ('view', $condition);
+  my @conditions;
+
+  push @conditions, "tag like '%$tag%'"           if $tag;
+  push @conditions, "region = '$region'"          if $region;
+  push @conditions, "ownerName like '$ownerName'" if $ownerName;
+
+  $condition = join " and ", @conditions if @conditions;
+
+  return $self->_getRecords('view', $condition);
 } # FindView
 
-sub AddFS (%) {
+sub AddFS(%) {
   my ($self, %fs) = @_;
-  
+
   my @requiredFields = (
     'system',
     'filesystem',
   );
 
   my $result = _checkRequiredFields \@requiredFields, \%fs;
-  
+
   return -1, "AddFS: $result"
     if $result;
-  
+
   # Timestamp record
   $fs{timestamp} = Today2SQLDatetime;
-  
-  return $self->_addRecord ('fs', %fs);
+
+  return $self->_addRecord('fs', %fs);
 } # AddFS
 
-sub TrimFS ($$) {
+sub TrimFS($$) {
   my ($self, $system, $filesystem) = @_;
-  
-  my %filesystem = $self->GetFilesystem ($system, $filesystem);
-  
-  return
-    unless %filesystem;
-   
-  my %task = $self->GetTask ('scrub');
-  
-  $self->Error ("Unable to find scrub task!", 1) unless %task;
-   
+
+  my %filesystem = $self->GetFilesystem($system, $filesystem);
+
+  return unless %filesystem;
+
+  my %task = $self->GetTask('scrub');
+
+  $self->Error("Unable to find scrub task!", 1) unless %task;
+
   my $days;
   my $today = Today2SQLDatetime;
-  
+
   # TODO: SubtractDays uses just an approximation (i.e. subtracting 30 days when
   # in February is not right.
   if ($filesystem{filesystemHist} =~ /(\d+) month/i) {
@@ -800,44 +824,42 @@ sub TrimFS ($$) {
   } # if
 
   my $oldage = SubtractDays $today, $days;
-  
-  my ($dberr, $dbmsg) = $self->_deleteRecord (
+
+  my ($dberr, $dbmsg) = $self->_deleteRecord(
     'fs',
     "system='$system' and filesystem='$filesystem' and timestamp<='$oldage'"
   );
-  
+
   if ($dbmsg eq 'Records deleted') {
-    return (0, $dbmsg)
-      if $dberr == 0;
-      
+    return (0, $dbmsg) if $dberr == 0;
+
     my %runlog;
-    
+
     $runlog{task}    = $task{name};
     $runlog{started} = $today;
     $runlog{status}  = 0;
-    $runlog{message} = 
+    $runlog{message} =
       "Scrubbed $dberr fs records for filesystem $system:$filesystem";
-    
-    my ($err, $msg) = $self->AddRunlog (%runlog);
-    
-    $self->Error ("Unable to add runlog - (Error: $err)\n$msg") if $err;
+
+    my ($err, $msg) = $self->AddRunlog(%runlog);
+
+    $self->Error("Unable to add runlog - (Error: $err)\n$msg") if $err;
   } # if
-  
+
   return ($dberr, $dbmsg);
 } # TrimFS
 
-sub TrimLoadavg ($) {
+sub TrimLoadavg($) {
   my ($self, $system) = @_;
-  
-  my %system = $self->GetSystem ($system);
-  
-  return
-    unless %system;
-    
-  my %task = $self->GetTask ('loadavg');
-  
-  $self->Error ("Unable to find loadavg task!", 1) unless %task;
-   
+
+  my %system = $self->GetSystem($system);
+
+  return unless %system;
+
+  my %task = $self->GetTask('loadavg');
+
+  $self->Error("Unable to find loadavg task!", 1) unless %task;
+
   my $days;
   my $today = Today2SQLDatetime;
 
@@ -850,45 +872,139 @@ sub TrimLoadavg ($) {
   } # if
 
   my $oldage = SubtractDays $today, $days;
-  
-  my ($dberr, $dbmsg) = $self->_deleteRecord (
+
+  my ($dberr, $dbmsg) = $self->_deleteRecord(
     'loadavg',
     "system='$system' and timestamp<='$oldage'"
   );
-  
+
   if ($dbmsg eq 'Records deleted') {
-    return (0, $dbmsg)
-      if $dberr == 0;
-      
+    return (0, $dbmsg) if $dberr == 0;
+
     my %runlog;
-    
+
     $runlog{task}    = $task{name};
     $runlog{started} = $today;
     $runlog{status}  = 0;
-    $runlog{message} = 
+    $runlog{message} =
       "Scrubbed $dberr loadavg records for system $system";
 
-    my ($err, $msg) = $self->AddRunlog (%runlog);
-    
-    $self->Error ("Unable to add runload (Error: $err)\n$msg") if $err;
+    my ($err, $msg) = $self->AddRunlog(%runlog);
+
+    $self->Error("Unable to add runload (Error: $err)\n$msg") if $err;
   } # if
 
   return ($dberr, $dbmsg);
 } # TrimLoadavg
 
-sub GetFS ($$;$$$$) {
+sub TrimStorage($$$) {
+  my ($self, $type, $tag, $region) = @_;
+
+  my $today = Today2SQLDatetime;
+
+  my $oldage = SubtractDays $today, $Clearadm::CLEAROPTS{CLEARADM_SCRUBDAYS};
+
+  my $table = $type =~ /vob/i
+            ? 'vobstorage'
+           : 'viewstorage';
+
+  my ($dberr, $dbmsg) = $self->_deleteRecord(
+    $table,
+    "tag='$tag' and region='$region' and timestamp<='$oldage'"
+  );
+
+  if ($dbmsg eq 'Records deleted') {
+    return (0, $dbmsg) if $dberr == 0;
+
+    my %runlog;
+
+    $runlog{task}    = 'Scrub';
+    $runlog{started} = $today;
+    $runlog{status}  = 0;
+    $runlog{message} =
+      "Scrubbed $dberr ${type}storage records";
+
+    my ($err, $msg) = $self->AddRunlog(%runlog);
+
+    $self->Error("Unable to add runload (Error: $err)\n$msg") if $err;
+  } # if
+
+  return ($dberr, $dbmsg);
+} # TrimStorage
+
+sub ValidateCCObjects() {
+  my ($self) = @_;
+
+  my $vobRecordsDeleted  = 0;
+  my $viewRecordsDeleted = 0;
+
+  for my $region ($Clearcase::CC->regions) {
+    for my $type (qw(vob view)) {
+      my @ccobjs;
+      verbose "Processing ${type}s in $region";
+
+      if ($type eq 'vob') {
+        verbose "Finding all vobs in region $region";
+       @ccobjs = $self->FindVob(undef, $region);
+       verbose 'Found ' . scalar @ccobjs . ' vobs to process';
+      } elsif ($type eq 'view') {
+        verbose "Finding all views in region $region";
+       @ccobjs = $self->FindView(undef, $region);
+       verbose 'Found ' . scalar @ccobjs . ' views to process';
+      } # if
+
+      for my $object (@ccobjs) {
+        my %ccobjrec = %$object;
+
+       verbose "Processing $ccobjrec{tag}:$ccobjrec{region}";
+
+       my $ccobj;
+
+       if ($type eq 'vob') {
+         $ccobj = Clearcase::Vob->new($ccobjrec{tag}, $ccobjrec{region});
+       } else {
+         $ccobj = Clearcase::View->new($ccobjrec{tag}, $ccobjrec{region});
+       } # if 
+
+       verbose_nolf 'Checking if ' . $ccobj->{tag} . ':' . $ccobj->{region} . ' exists anymore...';
+
+       if ($ccobj->exists) {
+         verbose ' it does! Skipping...';
+         next;
+       } else {
+         verbose ' it doesn\'t!';
+       } # if
+
+       #next if $ccobj->exists;
+
+       verbose "Deleting $type $ccobjrec{tag}:$ccobjrec{region}";
+
+       my ($recordsDeleted, $msg) = $self->_deleteRecord($type, 
+         "tag='$ccobjrec{tag}' and region='$ccobjrec{region}'");
+
+       if ($msg ne 'Records deleted') {
+         return ($recordsDeleted, $msg);
+       } else {
+         $viewRecordsDeleted += $recordsDeleted if $type eq 'view';
+         $vobRecordsDeleted  += $recordsDeleted if $type eq 'vob';
+       } # if
+      } # for
+    } # for
+  } # for
+
+  return ($viewRecordsDeleted, $vobRecordsDeleted);
+} # ValidateCCObjects
+
+sub GetFS($$;$$$$) {
   my ($self, $system, $filesystem, $start, $end, $count, $interval) = @_;
-  
-  $system = $self->_aliasSystem ($system);
-  
-  return
-    unless $system;
-    
-  return
-    unless $filesystem;
-    
+
+  $system = $self->_aliasSystem($system);
+
+  return unless $system;
+  return unless $filesystem;
+
   $interval ||= 'Minute';
-  
+
   my $size = $interval =~ /month/i
            ? 7
            : $interval =~ /day/i
@@ -896,32 +1012,32 @@ sub GetFS ($$;$$$$) {
            : $interval =~ /hour/i
            ? 13
            : 16;
-    
+
   undef $start if $start and $start =~ /earliest/i;
   undef $end   if $end   and $end   =~ /latest/i;
-  
+
   my $condition  = "system='$system' and filesystem='$filesystem'";
      $condition .= " and timestamp>='$start'" if $start;
      $condition .= " and timestamp<='$end'"   if $end;
-     
+
      $condition .= " group by left(timestamp,$size)";
-  
+
   if ($count) {
     # We can't simply do a "limit 0, $count" as that just gets the front end of
     # the records return (i.e. if $count = say 10 and the timestamp range
     # returns 40 rows we'll see only rows 1-10, not rows 31-40). We need limit
     # $offset, $count where $offset = the number of qualifying records minus
     # $count
-    my $nbrRecs = $self->Count ('fs', $condition);
+    my $nbrRecs = $self->Count('fs', $condition);
     my $offset  = $nbrRecs - $count;
-  
+
     # Offsets of < 0 are not allowed.
     $offset = 0
       if $offset < 0;
 
     $condition .= " limit $offset, $count";
   } # if
-       
+
   my $statement = <<"END";
 select
   system,
@@ -938,84 +1054,79 @@ from
 END
 
   my ($err, $msg);
-  
-  my $sth = $self->{db}->prepare ($statement);
-  
+
+  my $sth = $self->{db}->prepare($statement);
+
   unless ($sth) {
-    ($err, $msg) = $self->_dberror ('Unable to prepare statement', $statement);
-    
+    ($err, $msg) = $self->_dberror('Unable to prepare statement', $statement);
+
     croak $msg;
   } # if
-    
+
   my $status = $sth->execute;
-  
+
   unless ($status) {
-    ($err, $msg) = $self->_dberror ('Unable to execute statement', $statement);
-    
+    ($err, $msg) = $self->_dberror('Unable to execute statement', $statement);
+
     croak $msg;
   } # if
-    
+
   my @records;
-  
+
   while (my $row = $sth->fetchrow_hashref) {
     push @records, $row;
   } # while
-  
+
   return @records;
 } # GetFS
 
-sub GetLatestFS ($$) {
+sub GetLatestFS($$) {
   my ($self, $system, $filesystem) = @_;
-  
-  $system = $self->_aliasSystem ($system);
-  
-  return
-    unless $system;
-    
-  return
-    unless $filesystem;
-    
-  my @records = $self->_getRecords (
+
+  $system = $self->_aliasSystem($system);
+
+  return unless $system;
+  return unless $filesystem;
+
+  my @records = $self->_getRecords(
     'fs',
     "system='$system' and filesystem='$filesystem'"
   . " order by timestamp desc limit 0, 1",
   );
-  
+
   if ($records[0]) {
-       return %{$records[0]};
+    return %{$records[0]};
   } else {
-       return;
+    return;
   } # if
 } # GetLatestFS
 
-sub AddLoadavg () {
+sub AddLoadavg() {
   my ($self, %loadavg) = @_;
-  
+
   my @requiredFields = (
     'system',
   );
 
   my $result = _checkRequiredFields \@requiredFields, \%loadavg;
-  
-  return -1, "AddLoadavg: $result"
-    if $result;
-  
+
+  return -1, "AddLoadavg: $result" if $result;
+
   # Timestamp record
   $loadavg{timestamp} = Today2SQLDatetime;
-  
-  return $self->_addRecord ('loadavg', %loadavg);
+
+  return $self->_addRecord('loadavg', %loadavg);
 } # AddLoadavg
 
-sub GetLoadavg ($;$$$$) {
+sub GetLoadavg($;$$$$) {
   my ($self, $system, $start, $end, $count, $interval) = @_;
-           
-  $system = $self->_aliasSystem ($system);
-  
-  return
-    unless $system;
-    
+
+  $system = $self->_aliasSystem($system);
+
+  return unless $system;
+
   $interval ||= 'Minute';
-  
+
   my $size = $interval =~ /month/i
            ? 7
            : $interval =~ /day/i
@@ -1023,16 +1134,16 @@ sub GetLoadavg ($;$$$$) {
            : $interval =~ /hour/i
            ? 13
            : 16;
-    
+
   my $condition;
-  
+
   undef $start if $start and $start =~ /earliest/i;
   undef $end   if $end   and $end   =~ /latest/i;
-  
+
   $condition .= " system='$system'"        if $system;
   $condition .= " and timestamp>='$start'" if $start;
   $condition .= " and timestamp<='$end'"   if $end;
-  
+
   $condition .= " group by left(timestamp,$size)";
 
   if ($count) {
@@ -1041,16 +1152,15 @@ sub GetLoadavg ($;$$$$) {
     # returns 40 rows we'll see only rows 1-10, not rows 31-40). We need limit
     # $offset, $count where $offset = the number of qualifying records minus
     # $count
-    my $nbrRecs = $self->Count ('loadavg', $condition);
+    my $nbrRecs = $self->Count('loadavg', $condition);
     my $offset  = $nbrRecs - $count;
-  
+
     # Offsets of < 0 are not allowed.
-    $offset = 0
-      if $offset < 0;
+    $offset = 0 if $offset < 0;
 
     $condition .= " limit $offset, $count";
   } # if
-        
+
   my $statement = <<"END";
 select
   system,
@@ -1064,46 +1174,45 @@ from
 END
 
   my ($err, $msg);
-  
-  my $sth = $self->{db}->prepare ($statement);
-  
+
+  my $sth = $self->{db}->prepare($statement);
+
   unless ($sth) {
-    ($err, $msg) = $self->_dberror ('Unable to prepare statement', $statement);
-    
+    ($err, $msg) = $self->_dberror('Unable to prepare statement', $statement);
+
     croak $msg;
   } # if
-    
+
   my $status = $sth->execute;
-  
+
   unless ($status) {
-    ($err, $msg) = $self->_dberror ('Unable to execute statement', $statement);
-    
+    ($err, $msg) = $self->_dberror('Unable to execute statement', $statement);
+
     croak $msg;
   } # if
-    
+
   my @records;
-  
+
   while (my $row = $sth->fetchrow_hashref) {
     push @records, $row;
   } # while
-  
+
   return @records;
 } # GetLoadvg
 
-sub GetLatestLoadavg ($) {
+sub GetLatestLoadavg($) {
   my ($self, $system) = @_;
-  
-  $system = $self->_aliasSystem ($system);
-  
-  return
-    unless $system;
-    
-  my @records = $self->_getRecords (
+
+  $system = $self->_aliasSystem($system);
+
+  return unless $system;
+
+  my @records = $self->_getRecords(
     'loadavg',
     "system='$system'"
   . " order by timestamp desc limit 0, 1",
   );
-  
+
   if ($records[0]) {
     return %{$records[0]};
   } else {
@@ -1111,226 +1220,310 @@ sub GetLatestLoadavg ($) {
   } # if
 } # GetLatestLoadavg
 
-sub AddTask (%) {
+sub GetStoragePool($$$;$$$$$) {
+  my ($self, $type, $tag, $storage, $region, $start, $end, $count, $interval) = @_;
+
+  $interval ||= 'Day';
+  $region   ||= $Clearcase::CC->region;
+
+  return unless $type =~ /vob/i or $type =~ /view/;
+
+  my $size = $interval =~ /month/i
+           ? 7
+           : $interval =~ /day/i
+           ? 10
+           : $interval =~ /hour/i
+           ? 13
+           : 16;
+
+  undef $start if $start and $start =~ /earliest/i;
+  undef $end   if $end   and $end   =~ /latest/i;
+
+  # Windows vob tags begin with "\", which is problematic. The solution is to
+  # escape the "\"
+  $tag =~ s/^\\/\\\\/;
+
+  my $condition;
+  my $table = $type eq 'vob' ? 'vobstorage' : 'viewstorage';
+
+  $condition  = "tag='$tag' and region='$region'";
+  $condition .= " and timestamp>='$start'" if $start;
+  $condition .= " and timestamp<='$end'"   if $end;
+
+  $condition .= " group by left(timestamp,$size)";
+
+  if ($count) {
+    # We can't simply do a "limit 0, $count" as that just gets the front end of
+    # the records return (i.e. if $count = say 10 and the timestamp range
+    # returns 40 rows we'll see only rows 1-10, not rows 31-40). We need limit
+    # $offset, $count where $offset = the number of qualifying records minus
+    # $count
+    my $nbrRecs = $self->Count($table, $condition);
+    my $offset  = $nbrRecs - $count;
+
+    # Offsets of < 0 are not allowed.
+    $offset = 0 if $offset < 0;
+
+    $condition .= " limit $offset, $count";
+  } # if
+
+  my $statement = <<"END";
+select
+  tag,
+  region,
+  left(timestamp,$size) as timestamp,
+  avg($storage) as size
+from
+  $table
+  where $condition
+END
+
+  my ($err, $msg);
+
+  my $sth = $self->{db}->prepare($statement);
+
+  unless ($sth) {
+    ($err, $msg) = $self->_dberror('Unable to prepare statement', $statement);
+
+    croak $msg;
+  } # if
+
+  my $status = $sth->execute;
+
+  unless ($status) {
+    ($err, $msg) = $self->_dberror('Unable to execute statement', $statement);
+
+    croak $msg;
+  } # if
+
+  my @records;
+
+  while (my $row = $sth->fetchrow_hashref) {
+    push @records, $row;
+  } # while
+
+  return @records;
+} # GetStoragePool
+
+sub AddTask(%) {
   my ($self, %task) = @_;
-  
+
   my @requiredFields = (
     'name',
     'command'
   );
-  
+
   my $result = _checkRequiredFields \@requiredFields, \%task;
-  
-  return -1, "AddTask: $result"
-    if $result;
-  
-  return $self->_addRecord ('task', %task);    
+
+  return -1, "AddTask: $result" if $result;
+
+  return $self->_addRecord('task', %task);
 } # AddTask
 
-sub DeleteTask ($) {
+sub DeleteTask($) {
   my ($self, $name) = @_;
-  
-  return $self->_deleteRecord ('task', "name='$name'");
+
+  return $self->_deleteRecord('task', "name='$name'");
 } # DeleteTask
 
-sub FindTask ($) {
+sub FindTask($) {
   my ($self, $name) = @_;
-  
+
   $name ||= '';
-  
+
   my $condition = "name like '%$name%'";
-                
-  return $self->_getRecords ('task', $condition);
+
+  return $self->_getRecords('task', $condition);
 } # FindTask
 
-sub GetTask ($) {
+sub GetTask($) {
   my ($self, $name) = @_;
-  
-  return
-    unless $name;
-  
-  my @records = $self->_getRecords ('task', "name='$name'");
+
+  return unless $name;
+
+  my @records = $self->_getRecords('task', "name='$name'");
 
   if ($records[0]) {
     return %{$records[0]};
   } else {
     return;
-  } # if  
+  } # if
 } # GetTask
 
-sub UpdateTask ($%) {
+sub UpdateTask($%) {
   my ($self, $name, %update) = @_;
-  
-  return $self->_updateRecord ('task', "name='$name'", %update);
+
+  return $self->_updateRecord('task', "name='$name'", %update);
 } # Update
 
-sub AddSchedule (%) {
+sub AddSchedule(%) {
   my ($self, %schedule) = @_;
-  
+
   my @requiredFields = (
     'task',
   );
-  
+
   my $result = _checkRequiredFields \@requiredFields, \%schedule;
-  
-  return -1, "AddSchedule: $result"
-    if $result;
-  
-  return $self->_addRecord ('schedule', %schedule);    
+
+  return -1, "AddSchedule: $result" if $result;
+
+  return $self->_addRecord('schedule', %schedule);
 } # AddSchedule
 
-sub DeleteSchedule ($) {
+sub DeleteSchedule($) {
   my ($self, $name) = @_;
-  
-  return $self->_deleteRecord ('schedule', "name='$name'");
+
+  return $self->_deleteRecord('schedule', "name='$name'");
 } # DeleteSchedule
 
-sub FindSchedule (;$$) {
+sub FindSchedule(;$$) {
   my ($self, $name, $task) = @_;
-  
+
   $name ||= '';
-  $task||= '';
-  
+  $task ||= '';
+
   my $condition  = "name like '%$name%'";
      $condition .= ' and ';
      $condition .= "task like '%$task%'";
 
-  return $self->_getRecords ('schedule', $condition); 
+  return $self->_getRecords('schedule', $condition);
 } # FindSchedule
 
-sub GetSchedule ($) {
+sub GetSchedule($) {
   my ($self, $name) = @_;
-  
-  my @records = $self->_getRecords ('schedule', "name='$name'");
-  
+
+  my @records = $self->_getRecords('schedule', "name='$name'");
+
   if ($records[0]) {
     return %{$records[0]};
   } else {
     return;
-  } # if  
+  } # if
 } # GetSchedule
 
-sub UpdateSchedule ($%) {
+sub UpdateSchedule($%) {
   my ($self, $name, %update) = @_;
-  
-  return $self->_updateRecord ('schedule', "name='$name'", %update);
+
+  return $self->_updateRecord('schedule', "name='$name'", %update);
 } # UpdateSchedule
 
-sub AddRunlog (%) {
+sub AddRunlog(%) {
   my ($self, %runlog) = @_;
-  
+
   my @requiredFields = (
     'task',
   );
-  
+
   my $result = _checkRequiredFields \@requiredFields, \%runlog;
-  
-  return -1, "AddRunlog: $result"
-    if $result;
-  
+
+  return -1, "AddRunlog: $result" if $result;
+
   $runlog{ended} = Today2SQLDatetime;
-  
-  my ($err, $msg) = $self->_addRecord ('runlog', %runlog);
+
+  $runlog{system} = hostname if $runlog{system} =~ /localhost/i;
+
+  my ($err, $msg) = $self->_addRecord('runlog', %runlog);
 
   return ($err, $msg, $self->_getLastID);
 } # AddRunlog
 
-sub DeleteRunlog ($) {
+sub DeleteRunlog($) {
   my ($self, $condition) = @_;
-  
-  return $self->_deleteRecord ('runlog', $condition);
+
+  return $self->_deleteRecord('runlog', $condition);
 } # DeleteRunlog
 
-sub FindRunlog (;$$$$$$) {
+sub FindRunlog(;$$$$$$) {
   my ($self, $task, $system, $status, $id, $start, $page) = @_;
-  
-  $task ||= '';
-  
+
   # If ID is specified then that's all that really matters as it uniquely
   # identifies a runlog entry;
-  my $condition;
-  
+  my ($condition, $conditions);
+  my $limit = '';
+
   unless ($id) {
-    $condition  = "task like '%$task%'";
-    
-    if ($system) {
-      $condition .= " and system like '%$system%'"
-        unless $system eq 'All';
-    } else {
-      $condition .= ' and system is null';
-    } # unless
-        
-    if (defined $status) {
+    if ($task !~ /all/i) {
+      $conditions++;
+      $condition = "task like '%$task%'";
+    } # if
+
+    if ($system !~ /all/i) {
+      $condition .= ' and ' if $conditions;
+      $condition .= "system like '%$system%'";
+      $conditions++;
+    } # if
+
+    if ($status) {
+      $condition .= ' and ' if $conditions;
+
       if ($status =~ /!(-*\d+)/) {
-        $condition .= " and status<>$1";
+        $condition .= "status<>$1";
       } else {
-        $condition .= " and status=$status"
+        $condition .= "status=$status"
       } # if
     } # if
-    
-    $condition .= " order by started desc"; 
-    
+
+    # Need defined here as $start may be 0!
     if (defined $start) {
       $page ||= 10;
-      $condition .= " limit $start, $page";
+      $limit = "limit $start, $page";
     } # unless
   } else {
     $condition = "id=$id";
   } # unless
-  
-  return $self->_getRecords ('runlog', $condition);
+
+  return $self->_getRecords('runlog', $condition, " order by started desc $limit");
 } # FindRunlog
 
-sub GetRunlog ($) {
-  my ($self, $id) = @_;
-  
-  return
-    unless $id;
-  
-  my @records = $self->_getRecords ('runlog', "id=$id");
-  
+sub GetRunlog($) {
+  my ($self, $id) = @_;
+
+  return unless $id;
+
+  my @records = $self->_getRecords('runlog', "id=$id");
+
   if ($records[0]) {
     return %{$records[0]};
   } else {
     return;
-  } # if  
+  } # if
 } # GetRunlog
 
-sub UpdateRunlog ($%) {
+sub UpdateRunlog($%) {
   my ($self, $id, %update) = @_;
-  
-  return $self->_updateRecord ('runlog', "id=$id", %update);
+
+  return $self->_updateRecord('runlog', "id=$id", %update);
 } # UpdateRunlog
 
-sub Count ($;$) {
+sub Count($;$) {
   my ($self, $table, $condition) = @_;
-  
+
   $condition = $condition ? 'where ' . $condition : '';
-    
+
   my ($err, $msg);
-  
+
   my $statement = "select count(*) from $table $condition";
-  
-  my $sth = $self->{db}->prepare ($statement);
-  
+
+  my $sth = $self->{db}->prepare($statement);
+
   unless ($sth) {
-    ($err, $msg) = $self->_dberror ('Unable to prepare statement', $statement);
-    
+    ($err, $msg) = $self->_dberror('Unable to prepare statement', $statement);
+
     croak $msg;
   } # if
-    
+
   my $status = $sth->execute;
-  
+
   unless ($status) {
-    ($err, $msg) = $self->_dberror ('Unable to execute statement', $statement);
-    
+    ($err, $msg) = $self->_dberror('Unable to execute statement', $statement);
+
     croak $msg;
   } # if
-    
+
   # Hack! Statements such as the following:
   #
   # select count(*) from fs where system='jupiter' and filesystem='/dev/sdb5'
-  # > group by left(timestamp,10);                    
+  # > group by left(timestamp,10);
   # +----------+
   # | count(*) |
   # +----------+
@@ -1343,7 +1536,7 @@ sub Count ($;$) {
   # |      190 |
   # +----------+
   # 7 rows in set (0.00 sec)
-  # 
+  #
   # Here we want 7 but what we see in $records[0] is 49. So the hack is that if
   # statement contains "group by" then we assume we have the above and return
   # scalar @records, otherwise we return $records[0];
@@ -1363,11 +1556,11 @@ sub Count ($;$) {
 # execute the work to be done, timing it, and subtracting it from the $sleep
 # time returned. If the caller exhausts the $sleep time then they should call
 # us again.
-sub GetWork () {
+sub GetWork() {
   my ($self) = @_;
-  
+
   my ($err, $msg);
-  
+
   my $statement = <<"END";
 select
   schedule.name as schedulename,
@@ -1385,43 +1578,43 @@ where
   and schedule.active='true'
 order by lastrun
 END
-     
-  my $sth = $self->{db}->prepare ($statement);
-  
+
+  my $sth = $self->{db}->prepare($statement);
+
   unless ($sth) {
-    ($err, $msg) = $self->_dberror ('Unable to prepare statement', $statement);
-    
+    ($err, $msg) = $self->_dberror('Unable to prepare statement', $statement);
+
     croak $msg;
   } # if
-    
+
   my $status = $sth->execute;
-  
+
   unless ($status) {
-    ($err, $msg) = $self->_dberror ('Unable to execute statement', $statement);
-    
+    ($err, $msg) = $self->_dberror('Unable to execute statement', $statement);
+
     croak $msg;
   } # if
-  
-  my $sleep;  
+
+  my $sleep;
   my @records;
-  
+
   while (my $row = $sth->fetchrow_hashref) {
    if ($$row{system} !~ /localhost/i) {
-     my %system = $self->GetSystem ($$row{system});
-    
+     my %system = $self->GetSystem($$row{system});
+
      # Skip inactive systems
      next if $system{active} eq 'false';
    } # if
-    
+
     # If started is not defined then this task was never run so run it now.
     unless ($$row{lastrun}) {
       push @records, $row;
       next;
     } # unless
-    
+
     # TODO: Handle frequencies better.
     my $seconds;
-    
+
     if ($$row{frequency} =~ /(\d+) seconds/i) {
       $seconds = $1;
     } elsif ($$row{frequency} =~ /(\d+) minute/i) {
@@ -1434,23 +1627,23 @@ END
       warning "Don't know how to handle frequencies like $$row{frequency}";
       next;
     } # if
-    
+
     my $today    = Today2SQLDatetime;
-    my $lastrun  = Add ($$row{lastrun}, (seconds => $seconds));
-    my $waitTime = DateToEpoch ($lastrun) - DateToEpoch ($today);
-      
+    my $lastrun  = Add($$row{lastrun}, (seconds => $seconds));
+    my $waitTime = DateToEpoch($lastrun) - DateToEpoch($today);
+
     if ($waitTime < 0) {
       # We're late - push this onto records and move on
       push @records, $row;
     } # if
-    
+
     $sleep ||= $waitTime;
-    
+
     if ($sleep > $waitTime) {
       $sleep = $waitTime;
     } # if
   } # while
-  
+
   # Even if there is nothing to do the caller should sleep a bit and come back
   # to us. So if it ends up there's nothing past due, and nothing upcoming, then
   # sleep for a minute and return here. Somebody may have added a new task next
@@ -1458,94 +1651,93 @@ END
   if (@records == 0 and not $sleep) {
     $sleep = 60;
   } # if
-  
-  return ($sleep, @records);  
+
+  return ($sleep, @records);
 } # GetWork
 
-sub GetUniqueList ($$) {
+sub GetUniqueList($$) {
   my ($self, $table, $field) = @_;
-  
+
   my ($err, $msg);
-  
+
   my $statement = "select $field from $table group by $field";
-  
-  my $sth = $self->{db}->prepare ($statement);
-  
+
+  my $sth = $self->{db}->prepare($statement);
+
   unless ($sth) {
-    ($err, $msg) = $self->_dberror ('Unable to prepare statement', $statement);
-    
+    ($err, $msg) = $self->_dberror('Unable to prepare statement', $statement);
+
     croak $msg;
   } # if
-    
+
   my $status = $sth->execute;
-  
+
   unless ($status) {
-    ($err, $msg) = $self->_dberror ('Unable to execute statement', $statement);
-    
+    ($err, $msg) = $self->_dberror('Unable to execute statement', $statement);
+
     croak $msg;
   } # if
 
   my @values;
-  
+
   while (my @row = $sth->fetchrow_array) {
     if ($row[0]) {
       push @values, $row[0];
     } else {
       push @values, '<NULL>';
     } # if
-  } # foreach
+  } # for
 
   return @values;
 } # GetUniqueList
 
 sub AddAlert(%) {
   my ($self, %alert) = @_;
-  
+
   my @requiredFields = (
     'name',
     'type',
   );
-  
+
   my $result = _checkRequiredFields \@requiredFields, \%alert;
-  
-  return -1, "AddAlert: $result"
-    if $result;
-  
-  return $self->_addRecord ('alert', %alert);  
+
+  return -1, "AddAlert: $result" if $result;
+
+  return $self->_addRecord('alert', %alert);
 } # AddAlert
 
-sub DeleteAlert ($) {
+sub DeleteAlert($) {
   my ($self, $name) = @_;
-  
-  return $self->_deleteRecord ('alert', "name='$name'");
+
+  return $self->_deleteRecord('alert', "name='$name'");
 } # DeleteAlert
 
-sub FindAlert (;$) {
+sub FindAlert(;$) {
   my ($self, $alert) = @_;
-  
+
   $alert ||= '';
-  
+
   my $condition = "name like '%$alert%'";
-    
-  return $self->_getRecords ('alert', $condition);                
+
+  return $self->_getRecords('alert', $condition);
 } # FindAlert
 
-sub GetAlert ($) {
+sub GetAlert($) {
   my ($self, $name) = @_;
-  
+
   return
     unless $name;
-  
-  my @records = $self->_getRecords ('alert', "name='$name'");
-  
+
+  my @records = $self->_getRecords('alert', "name='$name'");
+
   if ($records[0]) {
     return %{$records[0]};
   } else {
     return;
-  } # if  
+  } # if
 } # GetAlert
 
-sub SendAlert ($$$$$$$) {
+sub SendAlert($$$$$$$) {
   my (
     $self,
     $alert,
@@ -1556,28 +1748,28 @@ sub SendAlert ($$$$$$$) {
     $to,
     $runlogID,
   ) = @_;
-  
+
   my $footing  = '<hr><p style="text-align: center;">';
      $footing .= '<font color="#bbbbbb">';
   my $year     = (localtime)[5] + 1900;
-     $footing .= "<a href='$CLEAROPTS{CLEARADM_WEBBASE}'>Clearadm</a><br>"; 
+     $footing .= "<a href='$CLEAROPTS{CLEARADM_WEBBASE}'>Clearadm</a><br>";
      $footing .= "Copyright &copy; $year, ClearSCM, Inc. - All rights reserved";
-  my %alert = $self->GetAlert ($alert);
-  
+
+  my %alert = $self->GetAlert($alert);
+
   if ($alert{type} eq 'email') {
     my $from = 'Clearadm@' . hostdomain;
-    
-    mail (
+
+    mail(
       from    => $from,
       to      => $to,
       subject => "Clearadm Alert: $system: $subject",
       mode    => 'html',
-      data    => $message, 
-      footing => $footing,     
+      data    => $message,
+      footing => $footing,
     );
   } else {
-    $self->Error ("Don't know how to send $alert{type} alerts\n"
+    $self->Error("Don't know how to send $alert{type} alerts\n"
                 . "Subject: $subject\n"
                 . "Message: $message", 1);
   } # if
@@ -1589,40 +1781,40 @@ sub SendAlert ($$$$$$$) {
     notification => $notification,
     runlog       => $runlogID,
     timestamp    => Today2SQLDatetime,
-    message      => $subject,  
-  );  
-  
-  return $self->AddAlertlog (%alertlog);
+    message      => $subject,
+  );
+
+  return $self->AddAlertlog(%alertlog);
 } # SendAlert
 
-sub GetLastAlert ($$) {
+sub GetLastAlert($$) {
   my ($self, $notification, $system) = @_;
-  
+
   my $statement = <<"END";
 select
   runlog,
   timestamp
-from 
+from
   alertlog
 where
       notification='$notification'
   and system='$system'
 order by
   timestamp desc
-limit 
+limit
   0, 1
 END
-                
-  my $sth = $self->{db}->prepare ($statement)
-    or return $self->_dberror ('Unable to prepare statement', $statement);
-    
+
+  my $sth = $self->{db}->prepare($statement)
+    or return $self->_dberror('Unable to prepare statement', $statement);
+
   $sth->execute
-    or return $self->_dberror ('Unable to execute statement', $statement);
-    
+    or return $self->_dberror('Unable to execute statement', $statement);
+
   my $alertlog= $sth->fetchrow_hashref;
-  
+
   $sth->finish;
-  
+
   if ($alertlog) {
     return %$alertlog;
   } else {
@@ -1630,40 +1822,40 @@ END
   } # if
 } # GetLastAlert
 
-sub GetLastTaskFailure ($$) {
+sub GetLastTaskFailure($$) {
   my ($self, $task, $system) = @_;
-  
+
   my $statement = <<"END";
 select
   id,
   ended
-from 
+from
   runlog
 where
-      status <> 0 
+      status <> 0
   and task='$task'
   and system='$system'
   and alerted='true'
 order by
   ended desc
-limit 
+limit
   0, 1
 END
-                
-  my $sth = $self->{db}->prepare ($statement)
-    or return $self->_dberror ('Unable to prepare statement', $statement);
-    
+
+  my $sth = $self->{db}->prepare($statement)
+    or return $self->_dberror('Unable to prepare statement', $statement);
+
   $sth->execute
-    or return $self->_dberror ('Unable to execute statement', $statement);
-    
+    or return $self->_dberror('Unable to execute statement', $statement);
+
   my $runlog= $sth->fetchrow_hashref;
-  
+
   $sth->finish;
-  
+
   if ($$runlog{ended}) {
     return %$runlog;
   } # if
-  
+
   # If we didn't get any ended in the last call then there's nothing that
   # qualified. Still let's return a record (%runlog) that has a valid id so
   # that the caller can update that runlog with alerted = 'true'.
@@ -1676,30 +1868,30 @@ where
       status <> 0
   and task='$task'
   and system='$system'
-order by 
+order by
   ended desc
 limit
   0, 1
 END
 
-  $sth = $self->{db}->prepare ($statement)
-    or return $self->_dberror ('Unable to prepare statement', $statement);
-      
+  $sth = $self->{db}->prepare($statement)
+    or return $self->_dberror('Unable to prepare statement', $statement);
+
   $sth->execute
-    or return $self->_dberror ('Unable to execute statement', $statement);
-      
+    or return $self->_dberror('Unable to execute statement', $statement);
+
   $runlog = $sth->fetchrow_hashref;
-    
+
   $sth->finish;
-    
+
   if ($runlog) {
     return %$runlog;
   } else {
     return
   } # if
-} # GetLastTaskFailure 
+} # GetLastTaskFailure
 
-sub Notify ($$$$$$) {
+sub Notify($$$$$$) {
   my (
     $self,
     $notification,
@@ -1713,65 +1905,64 @@ sub Notify ($$$$$$) {
 
   $runlogID = $self->_getLastID
     unless $runlogID;
-    
+
   my ($err, $msg);
-  
+
   # Update filesystem, if $filesystem was specified
   if ($filesystem) {
-    ($err, $msg) = $self->UpdateFilesystem (
+    ($err, $msg) = $self->UpdateFilesystem(
       $system,
       $filesystem, (
         notification => $notification,
       ),
     );
-    
-    $self->Error ("Unable to set notification for filesystem $system:$filesystem "
+
+    $self->Error("Unable to set notification for filesystem $system:$filesystem "
                . "(Status: $err)\n$msg", $err) if $err;
   } # if
-  
+
   # Update system
-  ($err, $msg) = $self->UpdateSystem (
+  ($err, $msg) = $self->UpdateSystem(
     $system, (
       notification => $notification,
     ),
   );
-  
-  my %notification = $self->GetNotification ($notification);
-  
-  my %lastnotified = $self->GetLastAlert ($notification, $system);
-  
+
+  my %notification = $self->GetNotification($notification);
+
+  my %lastnotified = $self->GetLastAlert($notification, $system);
+
   if (%lastnotified and $lastnotified{timestamp}) {
     my $today        = Today2SQLDatetime;
     my $lastnotified = $lastnotified{timestamp};
-      
+
     if ($notification{nomorethan} =~ /hour/i) {
-      $lastnotified = Add ($lastnotified, (hours => 1));
+      $lastnotified = Add($lastnotified, (hours => 1));
     } elsif ($notification{nomorethan} =~ /day/i) {
-      $lastnotified = Add ($lastnotified, (days => 1));
+      $lastnotified = Add($lastnotified, (days => 1));
     } elsif ($notification{nomorethan} =~ /week/i) {
-      $lastnotified = Add ($lastnotified, (days => 7));
+      $lastnotified = Add($lastnotified, (days => 7));
     } elsif ($notification{nomorethan} =~ /month/i) {
-      $lastnotified = Add ($lastnotified, (month => 1));
+      $lastnotified = Add($lastnotified, (month => 1));
     } # if
-      
+
     # If you want to fake an alert in the debugger just change $diff accordingly
-    my $diff = Compare ($today, $lastnotified);
-    
-    return
-      if $diff <= 0;
-  } # if  
+    my $diff = Compare($today, $lastnotified);
+
+    return if $diff <= 0;
+  } # if
 
   my $when       = Today2SQLDatetime;
   my $nomorethan = lc $notification{nomorethan};
-  my %alert      = $self->GetAlert ($notification{alert});
+  my %alert      = $self->GetAlert($notification{alert});
   my $to         = $alert{who};
 
   # If $to is null then this means to send the alert to the admin for the
   # machine.
   unless ($to) {
     if ($system) {
-      my %system = $self->GetSystem ($system);
-    
+      my %system = $self->GetSystem($system);
+
       $to = $system{email};
     } else {
       # If we don't know what system this error occurred on we'll have to notify
@@ -1780,14 +1971,14 @@ sub Notify ($$$$$$) {
       $to = $self->{NOTIFY};
     } # if
   } # unless
-  
+
   unless ($to) {
     Error "To undefined";
   } # unless
-  
+
   $message .= "<p>You will receive this alert no more than $nomorethan.</p>";
-  
-  ($err, $msg) = $self->SendAlert (
+
+  ($err, $msg) = $self->SendAlert(
     $notification{alert},
     $system,
     $notification{name},
@@ -1796,104 +1987,101 @@ sub Notify ($$$$$$) {
     $to,
     $runlogID,
   );
-  $self->Error ("Unable to send alert (Status: $err)\n$msg", $err) if $err;
+
+  $self->Error("Unable to send alert (Status: $err)\n$msg", $err) if $err;
 
   verbose "Sent alert to $to";
 
   # Update runlog to indicate we notified the user for this execution
-  ($err, $msg) = $self->UpdateRunlog (
+  ($err, $msg) = $self->UpdateRunlog(
     $runlogID, (
       alerted => 'true',
     ),
   );
-  
-  $self->Error ("Unable to update runlog (Status: $err)\n$msg", $err) if $err;
 
-  return;  
+  $self->Error("Unable to update runlog (Status: $err)\n$msg", $err) if $err;
+
+  return;
 } # Notify
 
-sub ClearNotifications ($$;$) {
+sub ClearNotifications($$;$) {
   my ($self, $system, $filesystem) = @_;
-  
+
   my ($err, $msg);
-  
+
   if ($filesystem) {
-    ($err, $msg) = $self->UpdateFilesystem (
+    ($err, $msg) = $self->UpdateFilesystem(
       $system,
       $filesystem, (notification => undef),
     );
-    
+
     error "Unable to clear notification for filesystem $system:$filesystem "
         . "(Status: $err)\n$msg", $err
       if $err;
-    
+
     # Check to see any of this system's filesystems have notifications. If none
-    # then it's save to say we've turned off the last notification for a 
+    # then it's save to say we've turned off the last notification for a
     # filesystem involved with this system and if $system{notification} was
     # 'Filesystem' then we can toggle off the notification on the system too
     my $filesystemsAlerted = 0;
-    
-    foreach ($self->FindFilesystem ($system)) {
-      $filesystemsAlerted++ 
+
+    for ($self->FindFilesystem($system)) {
+      $filesystemsAlerted++
         if $$_{notification};
-    } # foreach
-    
-    my %system = $self->GetSystem ($system);
-    
-    return
-      unless $system;
-      
-    if ($system{notification}                 and 
+    } # for
+
+    my %system = $self->GetSystem($system);
+
+    return unless $system;
+
+    if ($system{notification}                 and
         $system{notification} eq 'Filesystem' and
         $filesystemsAlerted == 0) {
-      ($err, $msg) = $self->UpdateSystem ($system, (notification => undef));
+      ($err, $msg) = $self->UpdateSystem($system, (notification => undef));
 
-      $self->Error ("Unable to clear notification for system $system "
+      $self->Error("Unable to clear notification for system $system "
                   . "(Status: $err)\n$msg", $err) if $err;
     } # if
   } else {
-    ($err, $msg) = $self->UpdateSystem ($system, (notification => undef));
-       
-    $self->Error ("Unable to clear notification for system $system "
+    ($err, $msg) = $self->UpdateSystem($system, (notification => undef));
+
+    $self->Error("Unable to clear notification for system $system "
                 . "(Status: $err)\n$msg", $err) if $err;
   } # if
-  
+
   return;
 } # ClearNotifications
 
-sub SystemAlive (%) {
+sub SystemAlive(%) {
   my ($self, %system) = @_;
 
   # If we've never heard from this system then we will assume that the system
   # has not been set up to run clearagent and has never checked in. In any event
-  # we cannot say the system died because we've never known it to be alive!  
-  return 1
-    unless $system{lastheardfrom};
-    
+  # we cannot say the system died because we've never known it to be alive!
+  return 1 unless $system{lastheardfrom};
+
   # If a system is not active (may have been temporarily been deactivated) then
   # we don't want to turn on the bells and whistles alerting people it's down.
-  return 1
-    if $system{active} eq 'false';
-    
+  return 1 if $system{active} eq 'false';
+
   my $today         = Today2SQLDatetime;
   my $lastheardfrom = $system{lastheardfrom};
-      
+
   my $tenMinutes = 10 * 60;
-  
-  $lastheardfrom = Add ($lastheardfrom, (seconds => $tenMinutes));
 
-  if (DateToEpoch ($lastheardfrom) < DateToEpoch ($today)) {
-    $self->UpdateSystem (
+  $lastheardfrom = Add($lastheardfrom, (seconds => $tenMinutes));
+
+  if (DateToEpoch($lastheardfrom) < DateToEpoch($today)) {
+    $self->UpdateSystem(
       $system{name}, (
         notification => 'Heartbeat'
       ),
     );
-   
+
     return;
   } else {
     if ($system{notification}) {
-      $self->UpdateSystem (
+      $self->UpdateSystem(
         $system{name}, (
           notification => undef
         ),
@@ -1903,155 +2091,185 @@ sub SystemAlive (%) {
   } # if
 } # SystemAlive
 
-sub UpdateAlert ($%) {
+sub UpdateAlert($%) {
   my ($self, $name, %update) = @_;
-  
-  return $self->_updateRecord (
+
+  return $self->_updateRecord(
     'alert',
     "name='$name'",
     %update
   );
 } # UpdateAlert
 
-sub AddAlertlog (%) {
+sub AddAlertlog(%) {
   my ($self, %alertlog) = @_;
-  
+
   my @requiredFields = (
     'alert',
     'notification',
   );
-  
+
   my $result = _checkRequiredFields \@requiredFields, \%alertlog;
-  
-  return -1, "AddAlertlog: $result"
-    if $result;
-  
+
+  return -1, "AddAlertlog: $result" if $result;
+
   # Timestamp record
   $alertlog{timestamp} = Today2SQLDatetime;
-  
-  return $self->_addRecord ('alertlog', %alertlog);  
+
+  return $self->_addRecord('alertlog', %alertlog);
 } # AddAlertlog
 
-sub DeleteAlertlog ($) {
+sub DeleteAlertlog($) {
   my ($self, $condition) = @_;
-  
+
   return
     unless $condition;
-    
+
   if ($condition =~ /all/i) {
-    return $self->_deleteRecord ('alertlog');
+    return $self->_deleteRecord('alertlog');
   } else {
-    return $self->_deleteRecord ('alertlog', $condition);
+    return $self->_deleteRecord('alertlog', $condition);
   } # if
 } # DeleteAlertlog
 
-sub FindAlertlog (;$$$$$) {
+sub FindAlertlog(;$$$$$) {
   my ($self, $alert, $system, $notification, $start, $page) = @_;
-  
+
   $alert        ||= '';
   $system       ||= '';
   $notification ||= '';
-  
+
   my $condition  = "alert like '%$alert%'";
      $condition .= ' and ';
      $condition .= "system like '%$system%'";
      $condition .= ' and ';
      $condition .= "notification like '%$notification%'";
      $condition .= " order by timestamp desc";
-     
-     if (defined $start) {
-       $page ||= 10;
-       $condition .= " limit $start, $page";
-     } # unless
 
-  return $self->_getRecords ('alertlog', $condition);
+  if (defined $start) {
+    $page ||= 10;
+    $condition .= " limit $start, $page";
+  } # unless
+
+  return $self->_getRecords('alertlog', $condition);
 } # FindAlertLog
 
-sub GetAlertlog ($) {
+sub GetAlertlog($) {
   my ($self, $alert) = @_;
-  
-  return
-    unless $alert;
-  
-  my @records = $self->_getRecords ('alertlog', "alert='$alert'");
-  
+
+  return unless $alert;
+
+  my @records = $self->_getRecords('alertlog', "alert='$alert'");
+
   if ($records[0]) {
     return %{$records[0]};
   } else {
     return;
-  } # if  
+  } # if
 } # GetAlertlog
 
-sub UpdateAlertlog ($%) {
+sub UpdateAlertlog($%) {
   my ($self, $alert, %update) = @_;
-  
-  return $self->_updateRecord (
+
+  return $self->_updateRecord(
     'alertlog',
     "alert='$alert'",
     %update
   );
 } # UpdateAlertlog
 
-sub AddNotification (%) {
+sub AddNotification(%) {
   my ($self, %notification) = @_;
-  
+
   my @requiredFields = (
     'name',
     'alert',
     'cond'
   );
-  
+
   my $result = _checkRequiredFields \@requiredFields, \%notification;
-  
-  return -1, "AddNotification: $result"
-    if $result;
-  
-  return $self->_addRecord ('notification', %notification);  
+
+  return -1, "AddNotification: $result" if $result;
+
+  return $self->_addRecord('notification', %notification);
 } # AddNotification
 
-sub DeleteNotification ($) {
+sub DeleteNotification($) {
   my ($self, $name) = @_;
-  
-  return $self->_deleteRecord ('notification', "name='$name'");
+
+  return $self->_deleteRecord('notification', "name='$name'");
 } # DeletePackage
 
-sub FindNotification (;$$) {
+sub FindNotification(;$$) {
   my ($self, $name, $cond, $ordering) = @_;
-  
+
   $name ||= '';
-  
+
   my $condition  = "name like '%$name%'";
      $condition .= " and $cond"
        if $cond;
-  
-  return $self->_getRecords ('notification', $condition);                
+
+  return $self->_getRecords('notification', $condition);
 } # FindNotification
 
-sub GetNotification ($) {
+sub GetNotification($) {
   my ($self, $name) = @_;
-  
-  return
-    unless $name;
-  
-  my @records = $self->_getRecords ('notification', "name='$name'");
-  
+
+  return unless $name;
+
+  my @records = $self->_getRecords('notification', "name='$name'");
+
   if ($records[0]) {
     return %{$records[0]};
   } else {
     return;
-  } # if  
+  } # if
 } # GetNotification
 
-sub UpdateNotification ($%) {
+sub UpdateNotification($%) {
   my ($self, $name, %update) = @_;
-  
-  return $self->_updateRecord (
+
+  return $self->_updateRecord(
     'notification',
     "name='$name'",
     %update
   );
 } # UpdateNotification
 
+sub AddVobStorage(%) {
+  my ($self, %vobstorage) = @_;
+
+  my @requiredFields = (
+    'tag',
+  );
+
+  my $result = _checkRequiredFields \@requiredFields, \%vobstorage;
+
+  return -1, "AddVobStorage: $result" if $result;
+
+  # Timestamp record
+  $vobstorage{timestamp} = Today2SQLDatetime;
+
+  return $self->_addRecord('vobstorage', %vobstorage);
+} # AddVobStorage
+
+sub AddViewStorage(%) {
+  my ($self, %viewstorage) = @_;
+
+  my @requiredFields = (
+    'tag',
+  );
+
+  my $result = _checkRequiredFields \@requiredFields, \%viewstorage;
+
+  return -1, "AddViewStorage: $result" if $result;
+
+  # Timestamp record
+  $viewstorage{timestamp} = Today2SQLDatetime;
+
+  return $self->_addRecord('viewstorage', %viewstorage);
+} # AddViewStorage
+
 1;
 
 =pod
@@ -2078,7 +2296,7 @@ L<Net::Domain|Net::Domain>
 
 =head2 ClearSCM Perl Modules
 
-=begin man 
+=begin man
 
  DateUtils
  Display