diff options
author | Kurt Zenker <kz@openoffice.org> | 2007-05-09 12:25:50 +0000 |
---|---|---|
committer | Kurt Zenker <kz@openoffice.org> | 2007-05-09 12:25:50 +0000 |
commit | ccc50f8a036670b6220332ff95bca8da85c2dd55 (patch) | |
tree | c441778e087483ef389c0edf1a98368f23bdfa31 /solenv/bin/build_client.pl | |
parent | 2adb53884509ddaab44d8b5b21326885296cd38f (diff) |
INTEGRATION: CWS vgbugs06 (1.1.2); FILE ADDED
2007/05/04 14:56:58 vg 1.1.2.10: #i74784# elaborated server pick
2007/04/26 14:40:24 vg 1.1.2.9: #i74784# default for server and client - choose the port automatically
2007/04/25 12:25:12 vg 1.1.2.8: #i74784# add handle same server as two parameters
2007/04/23 09:48:31 vg 1.1.2.7: #i74784# returned setenvstring fuctionality
2007/04/20 15:24:14 vg 1.1.2.6: #i74784# ensure temp files in temp dir
2007/04/20 09:51:46 vg 1.1.2.5: #i74784# set job env via %ENV hash
2007/03/21 14:31:24 vg 1.1.2.4: #i74784# more elaborated cleanup, more generic setsolar
2007/03/19 11:46:26 vg 1.1.2.3: #i74784#
2007/03/07 12:56:13 vg 1.1.2.2: #i74784#
2007/02/22 17:13:13 vg 1.1.2.1: #i74784# clienr for build tool
Diffstat (limited to 'solenv/bin/build_client.pl')
-rwxr-xr-x | solenv/bin/build_client.pl | 492 |
1 files changed, 492 insertions, 0 deletions
diff --git a/solenv/bin/build_client.pl b/solenv/bin/build_client.pl new file mode 100755 index 000000000000..7ceebbeb3a21 --- /dev/null +++ b/solenv/bin/build_client.pl @@ -0,0 +1,492 @@ +: +eval 'exec perl -S $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: build_client.pl,v $ +# +# $Revision: 1.2 $ +# +# last change: $Author: kz $ $Date: 2007-05-09 13:25:50 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* +# +# build_client - client for the build tool in server mode +# + +use strict; +use Socket; +use Sys::Hostname; +use File::Temp qw(tmpnam); +use POSIX; +use Cwd qw (cwd); + +$SIG{KILL} = \&handle_temp_files; +$SIG{INT} = \&handle_temp_files; + +### main ### +my $enable_multiprocessing = 1; +my $server_list_file; +my $server_list_time_stamp = 0; +my %ENV_BACKUP; +$ENV_BACKUP{$_} = $ENV{$_} foreach (keys %ENV); + +if ($^O eq 'MSWin32') { + eval { require Win32::Process; import Win32::Process; }; + $enable_multiprocessing = 0 if ($@); +} else { + use Cwd 'chdir'; +}; +my $processes_to_run = 1; + +my %hosts_ports = (); +my $default_port = 7890; +my @ARGV_COPY = @ARGV; # @ARGV BACKUP +#$ARGV_COPY{$_}++ foreach (@ARGV); +print "arguments: @ARGV\n"; +get_options(); + +my $proto = getprotobyname('tcp'); +my $paddr; +my $host = hostname(); +my $current_server = ''; +my $got_job = 0; +my %setsolar_scripts = (); +my @temp_files = (); +my %job_temp_files = (); +my %environments = (); # hash containing all environments +my $env_alias; +my %platform_rejects = (); # hash containing paddr of server, that replied "Wrong platform" + +my $child = 0; +if ($processes_to_run > 1) { + my $started_processes = 1; + if ($^O eq 'MSWin32') { + my $process_obj = undef; + my $child_args = "perl $0"; + foreach (@ARGV_COPY) { + /^-P(\d+)$/ and next; + /^-P$/ and shift @ARGV_COPY and next; + $child_args .= " $_"; + }; + do { + my $rc = Win32::Process::Create($process_obj, $^X, + $child_args, + 0, 0, #NORMAL_PRIORITY_CLASS, + "."); + print_error("Cannot start child process") if (!$rc); + $started_processes++; + } while ($started_processes < $processes_to_run); + } else { + my $pid; + do { + if ($pid = fork) { # parent + $started_processes++; + print $started_processes . "\n"; + } elsif (defined $pid) { # child + $child++; + }; + } while (($started_processes < $processes_to_run) && !$child); + }; +}; + +run_client(); +### end of main procedure ### + +######################### +# # +# Procedures # +# # +######################### +sub handle_temp_files { + print STDERR "Got signal - clearing up...\n"; + foreach (keys %job_temp_files) { + if ($job_temp_files{$_}) { + rename($_, $job_temp_files{$_}) or system("mv", $_, $job_temp_files{$_}); + print STDERR "Could not rename $_ to $job_temp_files{$_}\n" if (-e $_); + } else { + unlink $_ or system("rm -rf $_"); + print STDERR "Could not remove $_\n" if (-e $_); + }; + }; + exit($?); +}; + +sub run_client { +# initialize host and port + if (!scalar keys %hosts_ports) { + $hosts_ports{localhost} = $default_port; + } + + print "Started client with PID $$, hostname $host\n"; + + my $message = ''; + my $current_port = ''; + my %active_servers = (); + + do { + $got_job = 0; + foreach $current_server (keys %hosts_ports) { + foreach $current_port (keys %{$hosts_ports{$current_server}}) { + + #before each "inactive" server/port connect - connect to each "active" server/port + next if (defined ${$active_servers{$current_server}}{$current_port}); + # "active" cycle + foreach my $active_server (keys %active_servers) { + foreach my $active_port (keys %{$active_servers{$active_server}}) { +# print "Active: $active_server:$active_port\n"; + my $iaddr = inet_aton($active_server); + $paddr = sockaddr_in($active_port, $iaddr); + do { + my $server_is_active = 0; + $message = request_job($message, $active_server, $active_port); + $server_is_active++ if ($message); + if (!$server_is_active) { + delete ${$active_servers{$active_server}}{$active_port}; + # throw away obsolete environments + foreach (keys %environments) { + /^\d+@/; + if ($' eq "$active_server:$active_port") { + delete $environments{$_}; + }; + }; + }; + $message = '' if ($message eq 'No job'); + } while ($message); + }; + }; + + # "inactive" cycle +# print "Inactive: $current_server:$current_port\n"; + my $iaddr = inet_aton($current_server); + $paddr = sockaddr_in($current_port, $iaddr); + do { + $message = request_job($message, $current_server, $current_port); + if ($message) { + if (!defined $active_servers{$current_server}) { + my %ports; + $active_servers{$current_server} = \%ports; + }; + ${$active_servers{$current_server}}{$current_port}++; + }; + $message = '' if ($message eq 'No job'); + } while ($message); + }; + }; + sleep 5 if (!$got_job); + read_server_list(); + } while(1); +}; + +sub usage { + my $error = shift; + print STDERR "\nbuild_client\n"; + print STDERR "Syntax: build_client [-PN] host1[:port1:...:portN] [host2[:port1:...:portN] ... hostN[:port1:...:portN]]|\@server_list_file\n"; + print STDERR " -P - start multiprocessing build, with number of processes passed\n"; + print STDERR "Example1: build_client myserver1 myserver2:7891:7892\n"; + print STDERR " the client will be asking for jobs on myserver1's default ports (7890-7894)\n"; + print STDERR " and on myserver2's ports 7891 and 7892\n"; + print STDERR "Example2: build_client -P2 myserver1:7990 myserver2\n"; + print STDERR " start 2 clients which will be asking for jobs myserver1's port 7990\n"; + print STDERR " and myserver2's default ports (7890-7894)\n"; + exit ($error); +}; + +sub get_options { + my $arg; + usage(1) if (!scalar @ARGV); + while ($arg = shift @ARGV) { + usage(0) if /^--help$/; + usage(0) if /^-h$/; + $arg =~ /^-P(\d+)$/ and $processes_to_run = $1 and next; + $arg =~ /^-P$/ and $processes_to_run = shift @ARGV and next; + $arg =~ /^@(\S+)$/ and $server_list_file = $1 and next; + store_server($arg); + }; + if (($processes_to_run > 1) && (!$enable_multiprocessing)) { + print_error("Cannot load Win32::Process module for multiple client start"); + }; + if ($server_list_file) { + print_error("$server_list_file is not a regular file!!") if (!-f $server_list_file); + read_server_list(); + } + print_error("No server info") if (!scalar %hosts_ports); +}; + +sub store_server { + my $server_string = shift; + my @server_params = (); + @server_params = split (/:/, $server_string); + my $host = shift @server_params; + my @names = gethostbyname($host); + my $host_full_name = $names[0]; + my %ports = (); + if (defined $hosts_ports{$host_full_name}) { + %ports = %{$hosts_ports{$host_full_name}}; + }; + # To do: implement keys in form server:port -> priority + if (defined $hosts_ports{$host_full_name}) { + if (!$server_list_time_stamp) { + print "The $host with ip address " . inet_ntoa(inet_aton($host)) . " is at least two times in the server list\n"; + }; + } else { + print "Added server $host as $host_full_name\n"; + }; + if (scalar @server_params) { + $ports{$_}++ foreach (@server_params); + } else { + $ports{$_}++ foreach ($default_port .. $default_port + 4); + }; + $hosts_ports{$host_full_name} = \%ports; +}; + +sub read_server_list { + open(SERVER_LIST, "<$server_list_file") or return; + my $current_time_stamp = (stat($server_list_file))[9]; + return if ($server_list_time_stamp >= $current_time_stamp); + my @server_array = (); + foreach my $file_string(<SERVER_LIST>) { + while ($file_string =~ /(\S+)/) { + $file_string = $'; + store_server($1); + }; + }; + close SERVER_LIST; + $server_list_time_stamp = $current_time_stamp; +}; + +sub request_job { + my ($message, $current_server, $current_port) = @_; + $message = "platform=$ENV_BACKUP{OUTPATH} pid=$$ osname=$^O" if (!$message); + # create the socket, connect to the port + socket(SOCKET, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; + connect(SOCKET, $paddr) or return '';#die "connect: $!"; + my $error_code = 1; + $message .= "\n"; + syswrite SOCKET, $message, length $message; + while (my $line = <SOCKET>) { + chomp $line; + if ($line eq 'No job') { + close SOCKET or die "close: $!"; + return $line; + }; + if ($line eq "Wrong platform") { + if (!defined $platform_rejects{$paddr}) { + $platform_rejects{$paddr}++; + print STDERR $line . "\n"; + } + close SOCKET or die "close: $!"; + delete $hosts_ports{$current_server}; + return ''; + } elsif (defined $platform_rejects{$paddr}) { + delete $platform_rejects{$paddr}; + }; + $got_job++; + $error_code = do_job($line . " server=$current_server port=$current_port"); + } + close SOCKET or die "close: $!"; + return("result=$error_code pid=$$"); +} + +sub do_job { + my @job_parameters = split(/ /, shift); + my %job_hash = (); + my $last_param; + my $error_code; + print "Client $$@" . "$host\n"; + foreach (@job_parameters) { + if (/(=)/) { + $job_hash{$`} = $'; + $last_param = $`; + } else { + $job_hash{$last_param} .= " $_"; + }; + }; + $env_alias = $job_hash{server_pid} . '@' . $job_hash{server} . ':' . $job_hash{port}; + my $result = "1"; # default value + my $cmd_file = File::Temp::tmpnam($ENV_BACKUP{TMP}); + my $tmp_log_file = File::Temp::tmpnam($ENV_BACKUP{TMP}); + $job_temp_files{$tmp_log_file} = $job_hash{log}; + my $setenv_string = ''; + if (defined $job_hash{setenv_string}) { + # use configuration string from server + $setenv_string .= $job_hash{setenv_string}; + if ((defined $ENV{USE_SHELL}) && ($ENV{USE_SHELL} eq '4nt')) { + $cmd_file .= '.btm'; + }; + print "Environment: $setenv_string\n"; + + my $directory = $job_hash{job_dir}; + open (COMMAND_FILE, ">$cmd_file"); + print COMMAND_FILE "$setenv_string\n"; + if (!defined $job_hash{job_dir}) { + close COMMAND_FILE; + print "No job_dir, cmd file: $cmd_file\n"; + foreach (keys %job_hash) { + print "key: $_ $job_hash{$_}\n"; + }; + exit (1); + }; + + print COMMAND_FILE "pushd $job_hash{job_dir} && "; + print COMMAND_FILE $job_hash{job} ." >& $tmp_log_file\n"; + if ((defined $ENV{USE_SHELL}) && ($ENV{USE_SHELL} eq '4nt')) { + print COMMAND_FILE "exit %?\n"; + } else { + print COMMAND_FILE "exit \$?\n"; + }; + close COMMAND_FILE; + $job_temp_files{$cmd_file} = 0; + $job_temp_files{$tmp_log_file} = $job_hash{log}; + if ((defined $ENV{USE_SHELL}) && ($ENV{USE_SHELL} eq '4nt')) { + $error_code = system($ENV{COMSPEC}, '/c', $cmd_file); + } else { + $error_code = system($ENV{SHELL}, $cmd_file); + }; + unlink $cmd_file or system("rm -rf $cmd_file"); + delete $job_temp_files{$cmd_file}; + } else { + # generate setsolar string + if (!defined $environments{$env_alias}) { + $error_code = get_setsolar_environment(\%job_hash); + return($error_code) if ($error_code); + }; + my $solar_vars = $environments{$env_alias}; + + delete $ENV{$_} foreach (keys %ENV); + $ENV{$_} = $$solar_vars{$_} foreach (keys %$solar_vars); + print 'Workspace: '; + if (defined $ENV{CWS_WORK_STAMP}) { + print $ENV{CWS_WORK_STAMP}; + } else { + print $ENV{SOLARSRC}; + }; + + print "\nplatform: $ENV{INPATH} $^O"; + print "\ndir: $job_hash{job_dir}\n"; + print "job: $job_hash{job}\n"; + chdir $job_hash{job_dir}; + getcwd(); + my $job_string = $job_hash{job} . ' > ' . $tmp_log_file . ' 2>&1'; + $error_code = system($job_string); +# rename($tmp_log_file, $job_hash{log}) or system("mv", $tmp_log_file, $job_hash{log}); +# delete $job_temp_files{$tmp_log_file};# = $job_hash{log}; + }; + rename($tmp_log_file, $job_hash{log}) or system("mv", $tmp_log_file, $job_hash{log}); + delete $job_temp_files{$tmp_log_file}; + + if ($error_code) { + print "Error code = $error_code\n\n"; + } else { + print "Success!!\n\n"; + }; + return $error_code; +}; + +sub get_setsolar_environment { + my $job_hash = shift; + my $server_pid = $$job_hash{server_pid}; + my $setsolar_string = $$job_hash{setsolar_cmd}; + # Prepare the string for the client + $setsolar_string =~ s/\s-file\s\S+//g; + my $error_code = 0; + my $cmd_file = File::Temp::tmpnam($ENV_BACKUP{TMP}); + my $tmp_log_file = File::Temp::tmpnam($ENV_BACKUP{TMP}); + if ((defined $ENV{USE_SHELL}) && ($ENV{USE_SHELL} eq '4nt')) { + my $setsolar = $ENV{ENV_ROOT} . '/etools/setsolar.pl'; + $setsolar_string =~ s/^(\S+\s)\S+/$1$setsolar/; #replace the use of the local script with generic setsolar + $cmd_file .= '.btm'; + push(@temp_files, $cmd_file); + my $setsolar_tmp_file = File::Temp::tmpnam($ENV_BACKUP{TMP}); + $setsolar_tmp_file .= '.btm'; + open (COMMAND_FILE, ">$setsolar_tmp_file") or return $?; + print COMMAND_FILE "set SOURCE_ROOT=$$job_hash{source_root}\n" if ($$job_hash{source_root}); + print COMMAND_FILE "unset UPDATER\n" if (!defined $$job_hash{updater}); + print COMMAND_FILE "$setsolar_string -file $cmd_file"; + close COMMAND_FILE; + $error_code = system($ENV{COMSPEC}, '/c', $setsolar_tmp_file); + unlink $setsolar_tmp_file or system("rm -rf $setsolar_tmp_file"); + store_env_hash($cmd_file); + return $error_code; + }; + if (defined $$job_hash{updater}) { + $ENV{UPDATER} = $$job_hash{updater}; + } else { + undef $ENV{UPDATER} if (defined $ENV{UPDATER}); + }; + if (defined $$job_hash{source_root}) { + $ENV{SOURCE_ROOT} = $$job_hash{source_root}; + } else { + undef $ENV{SOURCE_ROOT} if (defined $ENV{SOURCE_ROOT}); + }; + $error_code = system("$setsolar_string -file $cmd_file"); + store_env_hash($cmd_file); + return $error_code; +}; + +sub print_error { + my $message = shift; + print STDERR "\nERROR: $message\n"; + exit(1); +}; +sub store_env_hash { + my $ss_setenv_file = shift;#($$job_hash{server_pid}.$$job_hash{setsolar_cmd}, $cmd_file); + my %solar_vars = (); + my $cmd_file = File::Temp::tmpnam($ENV_BACKUP{TMP}); + my $env_vars_file = File::Temp::tmpnam($ENV_BACKUP{TMP}); + print "$cmd_file $env_vars_file\n"; + #get all env variables in $env_vars_file + if ((defined $ENV{USE_SHELL}) && ($ENV{USE_SHELL} eq '4nt')) { + $cmd_file .= '.btm'; + open (COMMAND_FILE, ">$cmd_file"); + print COMMAND_FILE "call $ss_setenv_file\n"; + print COMMAND_FILE "set > $env_vars_file\n"; + close COMMAND_FILE; + system($ENV{COMSPEC}, '/c', $cmd_file); + } else { + open (COMMAND_FILE, ">$cmd_file"); + print COMMAND_FILE "source $ss_setenv_file\n"; + print COMMAND_FILE "env > $env_vars_file\n"; + close COMMAND_FILE; + system($ENV{SHELL}, $cmd_file); + }; + print_error($?) if ($?); + unlink $cmd_file or system("rm -rf $cmd_file"); + unlink $ss_setenv_file or system("rm -rf $ss_setenv_file"); + + open SOLARTABLE, "<$env_vars_file" or die "cant open solarfile $env_vars_file"; + while(<SOLARTABLE>) { + chomp; + s/\r\n//o; + /(=)/; + $solar_vars{$`} = $'; + }; + close SOLARTABLE; + unlink $env_vars_file or system("rm -rf $env_vars_file"); + $environments{$env_alias} = \%solar_vars; +}; |