#!/usr/bin/perl -w
######################################################################
#
# $Id: webjob-jqd-list-queues,v 1.9 2012/01/07 08:01:19 mavrik Exp $
#
######################################################################
#
# Copyright 2007-2012 The WebJob Project, All Rights Reserved.
#
######################################################################
#
# Purpose: List job queues.
#
######################################################################

use FindBin qw($Bin $RealBin); use lib ("$Bin/../lib/perl5/site_perl", "$RealBin/../lib/perl5/site_perl", "/usr/local/webjob/lib/perl5/site_perl", "/opt/local/webjob/lib/perl5/site_perl");

use strict;
use File::Basename;
use Getopt::Std;
use WebJob::JqdRoutines 1.024;
use WebJob::Properties 1.035;

BEGIN
{
  ####################################################################
  #
  # The Properties hash is essentially private. Those parts of the
  # program that wish to access or modify the data in this hash need
  # to call GetProperties() to obtain a reference.
  #
  ####################################################################

  my (%hProperties);

  ####################################################################
  #
  # Initialize regex variables.
  #
  ####################################################################

  $hProperties{'CommonRegexes'} = PropertiesGetGlobalRegexes();

  ####################################################################
  #
  # Define helper routines.
  #
  ####################################################################

  sub GetProperties
  {
    return \%hProperties;
  }
}

######################################################################
#
# Main Routine
#
######################################################################

  ####################################################################
  #
  # Punch in and go to work.
  #
  ####################################################################

  my ($phProperties);

  $phProperties = GetProperties();

  $$phProperties{'Program'} = basename(__FILE__);

  ####################################################################
  #
  # Get Options.
  #
  ####################################################################

  my (%hOptions);

  if (!getopts('d:s:t:', \%hOptions))
  {
    Usage($$phProperties{'Program'});
  }

  ####################################################################
  #
  # A job queue directory, '-d', is optional.
  #
  ####################################################################

  $$phProperties{'JobQueueDirectory'} = (exists($hOptions{'d'})) ? $hOptions{'d'} : "/var/webjob/spool/jqd";

  ####################################################################
  #
  # A queue state filter, '-s', is optional.
  #
  ####################################################################

  $$phProperties{'QueueState'} = (exists($hOptions{'s'})) ? lc($hOptions{'s'}) : "any";

  if (!defined($$phProperties{'QueueState'}) || $$phProperties{'QueueState'} !~ /^(?:any|active|frozen|locked)$/)
  {
    Usage($$phProperties{'Program'});
  }

  if ($$phProperties{'QueueState'} eq "any")
  {
    $$phProperties{'QueueStateRegex'} = qq((?:active|frozen|locked));
  }
  else
  {
    $$phProperties{'QueueStateRegex'} = qq($$phProperties{'QueueState'});
  }

  ####################################################################
  #
  # The queue type filter, '-t', is required.
  #
  ####################################################################

  $$phProperties{'QueueType'} = (exists($hOptions{'t'})) ? lc($hOptions{'t'}) : undef;

  if (!defined($$phProperties{'QueueType'}) || $$phProperties{'QueueType'} !~ /^(?:all|client|public)$/)
  {
    Usage($$phProperties{'Program'});
  }

  ####################################################################
  #
  # If any arguments remain, it's an error.
  #
  ####################################################################

  if (scalar(@ARGV) > 0)
  {
    Usage($$phProperties{'Program'});
  }

  ####################################################################
  #
  # Make sure the job queue directory exists.
  #
  ####################################################################

  if (!-d $$phProperties{'JobQueueDirectory'})
  {
    print STDERR "$$phProperties{'Program'}: Error='Base directory ($$phProperties{'JobQueueDirectory'}) does not exist.'\n";
    exit(2);
  }

  ####################################################################
  #
  # Create forward/reverse queue maps.
  #
  ####################################################################

  my (%hForwardQueueMap, %hQueueMapArgs, %hReverseQueueMap);

  %hQueueMapArgs =
  (
    'ForwardQueueMap'   => \%hForwardQueueMap,
    'JobQueueDirectory' => $$phProperties{'JobQueueDirectory'},
    'KeyRegex'          => "(?:" . $$phProperties{'CommonRegexes'}{'ClientId'} . "|" . $$phProperties{'CommonRegexes'}{'ClientSuppliedFilename'} . ")",
    'ReverseQueueMap'   => \%hReverseQueueMap,
    'SharedLock'        => 1,
    'ValueRegex'        => "\\d+",
  );
  if (!JqdSetupQueueMaps(\%hQueueMapArgs))
  {
    print STDERR "$$phProperties{'Program'}: Error='$hQueueMapArgs{'Error'}'\n";
    exit(2);
  }

  ####################################################################
  #
  # Read the job queue directory.
  #
  ####################################################################

  my (@aQueueFiles);

  if (!opendir(DIR, $$phProperties{'JobQueueDirectory'}))
  {
    print STDERR "$$phProperties{'Program'}: Error='Directory ($$phProperties{'JobQueueDirectory'}) could not be opened ($!).'\n";
    next;
  }
  @aQueueFiles = map("$$phProperties{'JobQueueDirectory'}/$_", sort(readdir(DIR)));

  ####################################################################
  #
  # Do some work.
  #
  ####################################################################

  foreach my $sQueueFile (@aQueueFiles)
  {
    my $sQueue = basename($sQueueFile);
    next if ($sQueue =~ /^\.{1,2}$/); # Ignore '.' and '..' entries.
    next if (!-d $sQueueFile || !-f "$sQueueFile/change.lock");
    next if ($$phProperties{'QueueType'} =~ /^client$/ &&   exists($hForwardQueueMap{$sQueue}) && $hForwardQueueMap{$sQueue} != 0);
    next if ($$phProperties{'QueueType'} =~ /^public$/ && (!exists($hForwardQueueMap{$sQueue}) || $hForwardQueueMap{$sQueue} == 0));
    my $sQueueState = JqdGetQueueState({ 'Directory' => $sQueueFile });
    if (!defined($sQueueState))
    {
      print STDERR "$$phProperties{'Program'}: Error='Unable to get queue state for $sQueue.'\n";
      next;
    }
    next if ($sQueueState !~ /^$$phProperties{'QueueStateRegex'}$/);
#FIXME Check queue directory structure before letting it pass.
    print $sQueue, "\n";
  }

  ####################################################################
  #
  # Shutdown and go home.
  #
  ####################################################################

  1;


######################################################################
#
# Usage
#
######################################################################

sub Usage
{
  my ($sProgram) = @_;
  print STDERR "\n";
  print STDERR "Usage: $sProgram [-d jqd-dir] [-s {any|active|frozen|locked}] -t {all|client|public}\n";
  print STDERR "\n";
  exit(1);
}


=pod

=head1 NAME

webjob-jqd-list-queues - List job queues.

=head1 SYNOPSIS

B<webjob-jqd-list-queues> B<[-d jqd-dir]> B<[-s {any|active|frozen|locked}]> B<-t {all|client|public}>

=head1 DESCRIPTION

This utility lists job queues.

=head1 OPTIONS

=over 4

=item B<-d jqd-dir>

Specifies the base directory where queues are to be created. This
directory must exist. The default value is /var/webjob/spool/jqd.

=item B<-s {any|active|frozen|locked}>

Restrict output based on the specified queue state.  Currently, the
following states are supported: 'any', 'active', 'frozen', and
'locked'.

=item B<-t {all|client|public}>

Restrict output based on the specified queue type.  Currently, the
following types are supported: 'all', 'client', and 'public'.

=back

=head1 AUTHOR

Klayton Monroe

=head1 SEE ALSO

webjob-jqd-create-queue(1), webjob-jqd-delete-queue(1)

=head1 LICENSE

All documentation and code are distributed under same terms and
conditions as B<WebJob>.

=cut
