Index: /trunk/DataStoreServer/scripts/Makefile.am
===================================================================
--- /trunk/DataStoreServer/scripts/Makefile.am	(revision 16875)
+++ /trunk/DataStoreServer/scripts/Makefile.am	(revision 16876)
@@ -4,4 +4,5 @@
 install_files = \
 	dsreg \
+        dsprodtool \
         dsrootindex \
         dsprodindex \
Index: /trunk/DataStoreServer/scripts/dsprodtool
===================================================================
--- /trunk/DataStoreServer/scripts/dsprodtool	(revision 16876)
+++ /trunk/DataStoreServer/scripts/dsprodtool	(revision 16876)
@@ -0,0 +1,256 @@
+#!/usr/bin/env perl
+#
+# Data Store product  create and delete
+#
+
+use strict;
+use warnings;
+
+use Getopt::Long qw( GetOptions );
+use DBI;
+use PS::IPP::Metadata::Config;
+use File::Copy;
+
+use PS::IPP::Config qw($PS_EXIT_SUCCESS
+		       $PS_EXIT_UNKNOWN_ERROR
+		       $PS_EXIT_SYS_ERROR
+		       $PS_EXIT_CONFIG_ERROR
+		       $PS_EXIT_PROG_ERROR
+		       $PS_EXIT_DATA_ERROR
+		       $PS_EXIT_TIMEOUT_ERROR
+		       metadataLookupStr
+		       metadataLookupBool
+		       caturi
+		       );
+my $product;
+
+my $ptype;
+my $description;
+
+my $ps0;
+my $ps1;
+my $ps2;
+my $ps3;
+my $ps4;
+my $ps5;
+my $ps6;
+my $ps7;
+
+my $ds_dir;
+
+my $add;
+my $del;
+my $remove;
+
+my $we_created_dir = 0;
+
+GetOptions(
+        'add'           =>      \$add,
+        'del'           =>      \$del,
+	'product=s'	=>	\$product,
+	'type=s'	=>	\$ptype,
+        'description=s' =>      \$description,
+        'rm'            =>      \$remove,
+	'ps0=s'		=>	\$ps0,          # product specific columns 0 - 7
+	'ps1=s'		=>	\$ps1,
+	'ps2=s'		=>	\$ps2,
+	'ps3=s'		=>	\$ps3,
+	'ps4=s'		=>	\$ps4,
+	'ps5=s'		=>	\$ps5,
+	'ps6=s'		=>	\$ps6,
+	'ps7=s'		=>	\$ps7
+) or pod2usage(2);
+
+my $err = "";
+
+$err .= "product is required\n" unless defined $product;
+
+# will exit if neither or both -add and -del were specified
+$err .= "Must specify either --add or --del.\n"
+    unless $add xor $del;
+
+if ($add) {
+    if (!$ptype) {
+        $err .= "need to specify Product type to add\n";
+    }
+    if (!$description) {
+        $err .= "need to specify Product description\n";
+    }
+
+}
+
+
+#
+# lookup the location of the Data Store
+#
+
+my $ipprc =  PS::IPP::Config->new(); # IPP Configuration
+my $siteConfig = $ipprc->{_siteConfig};
+if (!$ds_dir) {
+    $ds_dir = metadataLookupStr($ipprc->{_siteConfig}, 'PSTAMP_DATA_STORE_ROOT');
+    if (!$ds_dir) {
+        die("Data Store root directory not set");
+    }
+}
+
+my $root_index_script = "$ds_dir/index.txt";
+if (!stat($root_index_script)) {
+    $err .= "Data Store not found at '$ds_dir'.\n"
+}
+
+# bail if any of the above args were improper
+show_usage($err)
+    if ($err);
+
+my $dbserver = metadataLookupStr($siteConfig, 'DBSERVER');
+my $dbname   = metadataLookupStr($siteConfig, 'DBNAME');
+my $dbuser   = metadataLookupStr($siteConfig, 'DBUSER');
+my $dbpass   = metadataLookupStr($siteConfig, 'DBPASSWORD');
+exit ($PS_EXIT_CONFIG_ERROR) unless defined $dbserver and $dbname and $dbuser and $dbpass;
+
+my $dsn = "DBI:mysql:host=$dbserver;database=$dbname";
+
+my $dbh = DBI->connect($dsn, $dbuser, $dbpass) or die "Cannot connect to server\n";
+
+
+my $product_dir = "$ds_dir/$product";
+my $index_script_name = "$product_dir/index.txt";
+
+if ($del) {
+    #
+    # delete product
+    #
+    my $stmt = $dbh->prepare("SELECT prod_id, last_fs FROM dsProduct WHERE prod_name = \'$product\'");
+    $stmt->execute();
+    my $prod_row = $stmt->fetchrow_hashref();
+
+    if (!$prod_row) {
+        die("product $product not found");
+    }
+    my $prod_id = $prod_row->{prod_id};
+
+    # if requested, remove the product directory
+    if ($remove) {
+        if (system "rm -r $product_dir") {
+            die("failed to remove $product_dir");
+        }
+    } else  {
+        # otherwise just zap the index script
+        unlink("$index_script_name");
+    }
+
+
+    # loop over filesets in the product and delete them
+    $stmt = $dbh->prepare("SELECT fileset_id FROM dsFileset WHERE prod_id = $prod_id");
+    $stmt->execute();
+    my $fs_row;
+    while ($fs_row = $stmt->fetchrow_hashref()) {
+        my $fileset_id = $fs_row->{fileset_id};
+        $dbh->do("DELETE from dsFile where fileset_id = $fileset_id");
+        $dbh->do("DELETE from dsFileset where fileset_id = $fileset_id");
+    }
+    $dbh->do("DELETE from dsProduct where prod_id = $prod_id");
+
+    exit 0;
+
+} else {
+    #
+    # add a new product
+    #
+    my $stmt = $dbh->prepare("SELECT prod_id FROM dsProduct WHERE prod_name = \'$product\'");
+    $stmt->execute();
+    my $row = $stmt->fetchrow_hashref();
+
+    if ($row) {
+        die("product $product already exists");
+    }
+
+    # set up the product directory
+    if (! -e $product_dir) {
+        $we_created_dir = 1;
+        if (!mkdir $product_dir) {
+            die("failed trying to make product directory $product_dir");
+        }
+    }
+    if (-e $index_script_name ) {
+        if (!unlink($index_script_name)) {
+            die("failed trying to remove old $index_script_name");
+        }
+    }
+    if (!copy($root_index_script, $index_script_name)) {
+        print STDERR "failed trying to copy($root_index_script, $index_script_name)";
+        cleanup();
+        exit 1;
+    }
+
+    my $prodcolstr = make_prodcol_str($ps0, $ps1, $ps2, $ps3, $ps4, $ps5, $ps6, $ps7);
+
+    my $query = "INSERT INTO dsProduct (prod_name, last_update, type, description, " .
+                " prod_col_0, prod_col_1, prod_col_2, prod_col_3, prod_col_4, prod_col_5, prod_col_6, prod_col_7)" .
+                "VALUES('$product', UTC_TIMESTAMP(), '$ptype', '$description' $prodcolstr)"; 
+
+    my $count = $dbh->do($query);
+    if ($count == 0E0) {
+        print STDERR "failed to insert Product $product in database";
+        cleanup();
+        exit 1;
+    }
+
+
+
+    exit 0;
+}
+
+
+sub show_usage {
+    my $str = shift;
+
+    chomp $str;
+
+    my @tmp = split(/\//, $0);
+
+    pod2usage(
+        -msg => 
+"usage: $tmp[$#tmp] [--add|--del] --product prod_name --fileset fs_name --type fs_type [options]
+
+Commands:
+
+    --add        Add a new product with the given metadata options.
+    --del        Remove a product.
+
+Options:
+    --type      product type
+    --description Product Description
+    --ps0 - ps7 Optional product specific data
+    --rm        with --del remove the fileset directory from the Data Store
+    
+$str",
+        -exitval => 2
+    );
+}
+
+sub make_prodcol_str {
+
+    my @list = @_;
+    my $string = "";
+
+    foreach my $s (@list) {
+        if ($s) {
+            $string .= ", \'$s\'";
+        } else {
+            $string .= ", NULL";
+        }
+    }
+
+    return $string;
+}
+
+sub cleanup {
+    # don't delete the product directory unless we made it
+    if (!$we_created_dir) {
+        return 0;
+    }
+    if (system "rm -r $product_dir") {
+            print STDERR "failed to remove $product_dir";
+    }
+}
