#!/usr/bin/perl -w
######################################################################
#
# $Id: webjob-mldbm-set-config-kvps,v 1.17 2012/01/07 08:01:23 mavrik Exp $
#
######################################################################
#
# Copyright 2004-2012 The WebJob Project, All Rights Reserved.
#
######################################################################
#
# Purpose: Set config- or client-related key/value pairs.
#
######################################################################

use strict;
use Fcntl qw(:DEFAULT :flock);
use File::Basename;
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 Getopt::Std;
use WebJob::MldbmRoutines;
use WebJob::Properties 1.008;

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);

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

  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('c:d:r', \%hOptions))
  {
    Usage($$phProperties{'Program'});
  }

  ####################################################################
  #
  # A client ID, '-c', is required.
  #
  # N.B. We do not test the contents of this right away, because it
  # may not be a client ID after all.
  #
  ####################################################################

  $$phProperties{'ClientId'} = (exists($hOptions{'c'})) ? $hOptions{'c'} : undef;

  if (!defined($$phProperties{'ClientId'}))
  {
    Usage($$phProperties{'Program'});
  }

  ####################################################################
  #
  # A database, '-d', is optional.
  #
  ####################################################################

  $$phProperties{'DbFile'} = (exists($hOptions{'d'})) ? $hOptions{'d'} : "/var/webjob/db/mldbm/client.db";

  ####################################################################
  #
  # The reverse keys flag, '-r', is optional.
  #
  ####################################################################

  $$phProperties{'ReverseKeys'} = (exists($hOptions{'r'})) ? 1 : 0;

  ####################################################################
  #
  # If there isn't at least one argument left, it's an error.
  #
  ####################################################################

  if (scalar(@ARGV) < 1)
  {
    Usage($$phProperties{'Program'});
  }

  ####################################################################
  #
  # Connect to the specified DB.
  #
  ####################################################################

  my ($phDb, $phDbContext, $sLocalError);

  $phDbContext = MldbmNewContext
  (
    {
      'DbFile'     => $$phProperties{'DbFile'},
      'DbFlags'    => O_RDWR,
      'LockFlags'  => LOCK_EX,
      'LockMode'   => "+<",
    }
  );
  if (!MldbmConnect($phDbContext, \$sLocalError))
  {
    print STDERR "$$phProperties{'Program'}: Error='$sLocalError'\n";
    exit(2);
  }
  $phDb = $$phDbContext{'DbHandle'};

  ####################################################################
  #
  # Set the key/value pair(s). Add intermediate layers as required.
  #
  ####################################################################

  my $sKey;
  if ($$phProperties{'ReverseKeys'})
  {
    $sKey = $$phProperties{'ClientId'};
    if ($sKey !~ /^$$phProperties{'CommonRegexes'}{'MldbmKeyName'}$/)
    {
      print STDERR "$$phProperties{'Program'}: Key='$sKey' Error='Value does not pass muster.'\n";
      exit(2);
    }
  }
  else
  {
    if ($$phProperties{'ClientId'} !~ /^$$phProperties{'CommonRegexes'}{'ClientId'}$/)
    {
      print STDERR "$$phProperties{'Program'}: ClientId='$$phProperties{'ClientId'}' Error='Value does not pass muster.'\n";
      exit(2);
    }
  }

  foreach my $sKeyValuePair (@ARGV)
  {
    my ($sTempKey, $sValue) = ($sKeyValuePair =~ /^([^=]+)=(.*)$/);
    if ($$phProperties{'ReverseKeys'})
    {
      $$phProperties{'ClientId'} = $sTempKey;
      if ($$phProperties{'ClientId'} !~ /^$$phProperties{'CommonRegexes'}{'ClientId'}$/)
      {
        print STDERR "$$phProperties{'Program'}: ClientId='$$phProperties{'ClientId'}' Error='Value does not pass muster.'\n";
        next;
      }
    }
    else
    {
      $sKey = $sTempKey;
      if ($sKey !~ /^$$phProperties{'CommonRegexes'}{'MldbmKeyName'}$/)
      {
        print STDERR "$$phProperties{'Program'}: Key='$sKey' Error='Value does not pass muster.'\n";
        next;
      }
    }
    my %hKeys = ( $sKey => $sValue );
    my %hClient = ( 'Config' => \%hKeys );

    if (exists($$phDb{$$phProperties{'ClientId'}}))
    {
      my $phClient = $$phDb{$$phProperties{'ClientId'}};
      if (exists($$phClient{'Config'}))
      {
        my $phKeys = $$phClient{'Config'};
        $$phKeys{$sKey} = $sValue,
      }
      else
      {
        $$phClient{'Config'} = \%hKeys;
      }
      $$phDb{$$phProperties{'ClientId'}} = $phClient;
    }
    else
    {
      $$phDb{$$phProperties{'ClientId'}} = \%hClient;
    }
  }

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

  MldbmDisconnect($phDbContext, \$sLocalError);

  1;


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

sub Usage
{
  my ($sProgram) = @_;
  print STDERR "\n";
  print STDERR "Usage: $sProgram [-r] [-d db] -c client-id key=value [key=value ...]\n";
  print STDERR "\n";
  exit(1);
}


=pod

=head1 NAME

webjob-mldbm-set-config-kvps - Set config- or client-related key/value pairs.

=head1 SYNOPSIS

B<webjob-mldbm-set-config-kvps> B<[-r]> B<[-d db]> B<-c client-id> B<key=value [key=value ...]>

=head1 DESCRIPTION

This utility sets config- or client-related key/value pairs.

=head1 OPTIONS

=over 4

=item B<-c client-id>

Specifies the client ID to update.

=item B<-d db>

Specifies the MLDBM database to update.

=item B<-r>

Reverse the meaning of the B<clientid> and B<key> arguments. This
option allows you to set the value of a single key for each
client/value pair specified.

=back

=head1 AUTHOR

Klayton Monroe

=head1 SEE ALSO

webjob-mldbm-get-config-kvps(1)

=head1 LICENSE

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

=cut
