#!/usr/bin/perl
# 
# program to query the DB relay
# written by Thomas.Bergauer@cern.ch
#
# version history:
# 1.0 first try
# 1.1 includes parsing of "status" flag for debugging
# 1.2 includes "verbose" flag, filereading and new table output
# 2.0 completly rewritten parser, remarks in input file possible
# 2.1 new flags: -h, -s
# 2.2 fixed bug with -h flag

use XML::Parser;
use Getopt::Std;

#
# some variables

$port = 3615;
$host = 'cmstrkdb.in2p3.fr';


$AF_INET = 2;
$SOCK_STREAM = 1;

    
#
# handle INT signals
$SIG{'INT'} = 'dokill';
sub dokill {
    kill 9,$child if $child;
}


# check options
my %opts = ();getopts('vsh', \%opts);
$verbose = $opts{'v'};
$readfromstdin = $opts{'s'};
$noheader = $opts{'h'};

# read filename from argumentlist
$file = $ARGV[0];


#
# read query
if ($readfromstdin) {
  # read query from stdin
  @filelines = <STDIN>
  }
else
  {
  # print usage if no filename given
  if ($file eq "") {
    print "\nTrackerDB relay application query program V2.2\n";
    print "by Thomas.Bergauer\@cern.ch\n\n";
    print "usage:\n";
    print "  relay.pl [OPTIONS] filename.sql\n\n";
    print "options:\n";
    print "  -v:  verbose. print query and db status.\n";
    print "  -h:  no header. suppress column name in answer.\n";
    print "  -s:  read query from stdin and not from file.\n";
    print "       (example: cat file.sql |relay.pl -s)\n";
    print "\n";
    exit 1;
  }
  # read query from file
  open(QUERY, $file) || die "file not found" ;
  @filelines = <QUERY>;				# read file to arry
  close(QUERY);
  }

# remove lines beginning with '#' (remarks)
@lines = grep(!/^#/, @filelines);

#
# connect to relay server at Lyon

$sockaddr = 'S n a4 x8';
#chop($hostname = `hostname`);
($name,$aliases,$proto) = getprotobyname('tcp');
($name,$aliases,$port) = getservbyname($port,'tcp')
    unless $port =~ /^\d+$/;;
($name,$aliases,$type,$len,$thisaddr) =
	gethostbyname($hostname);
($name,$aliases,$type,$len,$thataddr) = gethostbyname($host);

$this = pack($sockaddr, $AF_INET, 0, $thisaddr);
$that = pack($sockaddr, $AF_INET, $port, $thataddr);
if (socket(S, $AF_INET, $SOCK_STREAM, $proto)) {
}
else {
    print "** socket error\n";
    die $!;
}
if (bind(S, $this)) {
}
else {
    print "** bind error\n";
    die $!;
}
if (connect(S,$that)) {
}
else {
    print "** connect error\n";
    die $!;
}
select(S); $| = 1; select(STDOUT);



# print xml file to socket
# and to stdout if verbose
if ($verbose) {  print @lines,"\n"; }
print S @lines,"\n";



# define parser
$parser = new XML::Parser( Handlers => {
				Start => \&handle_start, # starttag
				End => \&handle_end, # endtag
				Char => \&handle_char,   # value between tags
				Final => \&final_handler}); # after last tag

$parser->parse(*S); # parse the answer from socket
#print "\n\n";
exit 0;

#
# program end
#

# *************************************************************
# handler for start tags
sub handle_start {
  # read local variables
  my($p,$el) = @_;
  #make tag global
  $tag=$el;
  $state="starttag";
}

# *************************************************************
# handler for start tags
sub handle_end {
  # read local variables
  my($p,$el) = @_;
  #make tag global
  $tag=$el;
  if ($tag eq "row") { 
	if ((! $noheader) or !($linecount == 0)) { print $line,"\n"; } 
	$line = ""; 
	if ($linecount == 0) { print $line2,"\n"; $line2=""; }
	$linecount++; 
	}
  if ($tag eq "value") { 
	$line  = $line  . "\t";  
	$line2 = $line2 . "\t"; 
}
  $state="endtag";
}

# *************************************************************
# handler for data between tags
sub handle_char {
  my($p,$val) = @_;


  # TAG "status"
  if    ($tag eq "status")  { 
	if (($verbose or $val =~ 400 ) and $state eq "starttag" ) { 
		print STDERR "Status: ",$val,"\n\n";
	} 
  }

 # first line
 if ($linecount == 0) { 

  if ($tag eq "column") { $line = $line . $val; }
  if ($tag eq "value")  { $line2 = $line2 . $val; }

 }
 else { 

 # second, third,... line
  if ($tag eq "value") { $line = $line . $val; }


 }

 $state="textbetween";
}


# *************************************************************
# handler after last tag
sub final_handler {
  my($p,$val) = @_;
#  print $val;
}

