2 eval 'exec perl -S $0 ${1+"$@"}'
4 #*************************************************************************
6 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 # Copyright 2000, 2010 Oracle and/or its affiliates.
10 # OpenOffice.org - a multi-platform office productivity suite
12 # This file is part of OpenOffice.org.
14 # OpenOffice.org is free software: you can redistribute it and/or modify
15 # it under the terms of the GNU Lesser General Public License version 3
16 # only, as published by the Free Software Foundation.
18 # OpenOffice.org is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU Lesser General Public License version 3 for more details
22 # (a copy is included in the LICENSE file that accompanied this code).
24 # You should have received a copy of the GNU Lesser General Public License
25 # version 3 along with OpenOffice.org. If not, see
26 # <http://www.openoffice.org/license.html>
27 # for a copy of the LGPLv3 License.
29 #*************************************************************************
31 # build_client - client for the build tool in server mode
37 use File
::Temp
qw(tmpnam);
41 $SIG{KILL
} = \
&handle_temp_files
;
42 $SIG{INT
} = \
&handle_temp_files
;
45 my $enable_multiprocessing = 1;
47 my $server_list_time_stamp = 0;
49 $ENV_BACKUP{$_} = $ENV{$_} foreach (keys %ENV);
51 if ($^O
eq 'MSWin32') {
52 eval { require Win32
::Process
; import Win32
::Process
; };
53 $enable_multiprocessing = 0 if ($@
);
57 my $processes_to_run = 1;
60 my $default_port = 7890;
61 my @ARGV_COPY = @ARGV; # @ARGV BACKUP
62 #$ARGV_COPY{$_}++ foreach (@ARGV);
63 print "arguments: @ARGV\n";
66 my $proto = getprotobyname('tcp');
68 my $host = hostname
();
69 my $current_server = '';
71 my %job_temp_files = ();
72 my %environments = (); # hash containing all environments
74 my %platform_rejects = (); # hash containing paddr of server, that replied "Wrong platform"
77 if ($processes_to_run > 1) {
78 my $started_processes = 1;
79 if ($^O
eq 'MSWin32') {
80 my $process_obj = undef;
81 my $child_args = "perl $0";
82 foreach (@ARGV_COPY) {
84 /^-P$/ and shift @ARGV_COPY and next;
88 my $rc = Win32
::Process
::Create
($process_obj, $^X
,
90 0, 0, #NORMAL_PRIORITY_CLASS,
92 print_error
("Cannot start child process") if (!$rc);
94 } while ($started_processes < $processes_to_run);
98 if ($pid = fork) { # parent
100 print $started_processes . "\n";
101 } elsif (defined $pid) { # child
104 } while (($started_processes < $processes_to_run) && !$child);
109 ### end of main procedure ###
111 #########################
115 #########################
116 sub handle_temp_files
{
117 print STDERR
"Got signal - clearing up...\n";
118 foreach (keys %job_temp_files) {
119 if ($job_temp_files{$_}) {
120 rename($_, $job_temp_files{$_}) or system("mv", $_, $job_temp_files{$_});
121 print STDERR
"Could not rename $_ to $job_temp_files{$_}\n" if (-e
$_);
123 unlink $_ or system("rm -rf $_");
124 print STDERR
"Could not remove $_\n" if (-e
$_);
131 # initialize host and port
132 if (!scalar keys %hosts_ports) {
133 $hosts_ports{localhost
} = $default_port;
136 print "Started client with PID $$, hostname $host\n";
139 my $current_port = '';
140 my %active_servers = ();
144 foreach $current_server (keys %hosts_ports) {
145 foreach $current_port (keys %{$hosts_ports{$current_server}}) {
147 #before each "inactive" server/port connect - connect to each "active" server/port
148 next if (defined ${$active_servers{$current_server}}{$current_port});
150 foreach my $active_server (keys %active_servers) {
151 foreach my $active_port (keys %{$active_servers{$active_server}}) {
152 # print "Active: $active_server:$active_port\n";
153 my $iaddr = inet_aton
($active_server);
154 $paddr = sockaddr_in
($active_port, $iaddr);
156 my $server_is_active = 0;
157 $message = request_job
($message, $active_server, $active_port);
158 $server_is_active++ if ($message);
159 if (!$server_is_active) {
160 delete ${$active_servers{$active_server}}{$active_port};
161 # throw away obsolete environments
162 foreach (keys %environments) {
164 if ($' eq "$active_server:$active_port") {
165 delete $environments{$_};
169 $message = '' if ($message eq 'No job
');
175 # print "Inactive: $current_server:$current_port\n";
176 my $iaddr = inet_aton($current_server);
177 $paddr = sockaddr_in($current_port, $iaddr);
179 $message = request_job($message, $current_server, $current_port);
181 if (!defined $active_servers{$current_server}) {
183 $active_servers{$current_server} = \%ports;
185 ${$active_servers{$current_server}}{$current_port}++;
187 $message = '' if ($message eq 'No job
');
191 sleep 5 if (!$got_job);
198 print STDERR "\nbuild_client\n";
199 print STDERR "Syntax: build_client [-PN] host1[:port1:...:portN] [host2[:port1:...:portN] ... hostN[:port1:...:portN]]|\@server_list_file\n";
200 print STDERR " -P - start multiprocessing build, with number of processes passed\n";
201 print STDERR "Example1: build_client myserver1 myserver2:7891:7892\n";
202 print STDERR " the client will be asking for jobs on myserver1's
default ports
(7890-7894)\n";
203 print STDERR " and on myserver2
's ports 7891 and 7892\n";
204 print STDERR "Example2: build_client -P2 myserver1:7990 myserver2\n";
205 print STDERR " start 2 clients which will be asking for jobs myserver1's port
7990\n";
206 print STDERR " and myserver2
's default ports (7890-7894)\n";
212 usage(1) if (!scalar @ARGV);
213 while ($arg = shift @ARGV) {
214 usage(0) if /^--help$/;
216 $arg =~ /^-P(\d+)$/ and $processes_to_run = $1 and next;
217 $arg =~ /^-P$/ and $processes_to_run = shift @ARGV and next;
218 $arg =~ /^@(\S+)$/ and $server_list_file = $1 and next;
221 if (($processes_to_run > 1) && (!$enable_multiprocessing)) {
222 print_error("Cannot load Win32::Process module for multiple client start");
224 if ($server_list_file) {
225 print_error("$server_list_file is not a regular file!!") if (!-f $server_list_file);
228 print_error("No server info") if (!scalar %hosts_ports);
232 my $server_string = shift;
233 my @server_params = ();
234 @server_params = split (/:/, $server_string);
235 my $host = shift @server_params;
236 my @names = gethostbyname($host);
237 my $host_full_name = $names[0];
239 if (defined $hosts_ports{$host_full_name}) {
240 %ports = %{$hosts_ports{$host_full_name}};
242 # To do: implement keys in form server:port -> priority
243 if (defined $hosts_ports{$host_full_name}) {
244 if (!$server_list_time_stamp) {
245 print "The $host with ip address " . inet_ntoa(inet_aton($host)) . " is at least two times in the server list\n";
248 print "Added server $host as $host_full_name\n";
250 if (scalar @server_params) {
251 $ports{$_}++ foreach (@server_params);
253 $ports{$_}++ foreach ($default_port .. $default_port + 4);
255 $hosts_ports{$host_full_name} = \%ports;
258 sub read_server_list {
259 open(SERVER_LIST, "<$server_list_file") or return;
260 my $current_time_stamp = (stat($server_list_file))[9];
261 return if ($server_list_time_stamp >= $current_time_stamp);
262 my @server_array = ();
263 foreach my $file_string(<SERVER_LIST>) {
264 while ($file_string =~ /(\S+)/) {
270 $server_list_time_stamp = $current_time_stamp;
274 my ($message, $current_server, $current_port) = @_;
275 $message = "platform=$ENV_BACKUP{OUTPATH} pid=$$ osname=$^O" if (!$message);
276 # create the socket, connect to the port
277 socket(SOCKET
, PF_INET
, SOCK_STREAM
, $proto) or die "socket: $!";
278 connect(SOCKET
, $paddr) or return '';#die "connect: $!";
281 syswrite SOCKET
, $message, length $message;
282 while (my $line = <SOCKET
>) {
284 if ($line eq 'No job') {
285 close SOCKET
or die "close: $!";
288 if ($line eq "Wrong platform") {
289 if (!defined $platform_rejects{$paddr}) {
290 $platform_rejects{$paddr}++;
291 print STDERR
$line . "\n";
293 close SOCKET
or die "close: $!";
294 delete $hosts_ports{$current_server};
296 } elsif (defined $platform_rejects{$paddr}) {
297 delete $platform_rejects{$paddr};
300 $error_code = do_job
($line . " server=$current_server port=$current_port");
302 close SOCKET
or die "close: $!";
303 return("result=$error_code pid=$$");
307 my @job_parameters = split(/ /, shift);
311 print "Client $$@" . "$host\n";
312 foreach (@job_parameters) {
317 $job_hash{$last_param} .= " $_";
320 $env_alias = $job_hash{server_pid
} . '@' . $job_hash{server
} . ':' . $job_hash{port
};
321 my $result = "1"; # default value
322 my $cmd_file = File
::Temp
::tmpnam
($ENV_BACKUP{TMP
});
323 my $tmp_log_file = File
::Temp
::tmpnam
($ENV_BACKUP{TMP
});
324 $job_temp_files{$tmp_log_file} = $job_hash{log};
325 my $setenv_string = '';
326 if (defined $job_hash{setenv_string
}) {
327 # use configuration string from server
328 $setenv_string .= $job_hash{setenv_string
};
329 print "Environment: $setenv_string\n";
331 my $directory = $job_hash{job_dir
};
332 open (COMMAND_FILE
, ">$cmd_file");
333 print COMMAND_FILE
"$setenv_string\n";
334 if (!defined $job_hash{job_dir
}) {
336 print "No job_dir, cmd file: $cmd_file\n";
337 foreach (keys %job_hash) {
338 print "key: $_ $job_hash{$_}\n";
343 print COMMAND_FILE
"pushd $job_hash{job_dir} && ";
344 print COMMAND_FILE
$job_hash{job
} ." >& $tmp_log_file\n";
345 print COMMAND_FILE
"exit \$?\n";
347 $job_temp_files{$cmd_file} = 0;
348 $job_temp_files{$tmp_log_file} = $job_hash{log};
349 $error_code = system($ENV{SHELL
}, $cmd_file);
350 unlink $cmd_file or system("rm -rf $cmd_file");
351 delete $job_temp_files{$cmd_file};
353 # generate setsolar string
354 if (!defined $environments{$env_alias}) {
355 $error_code = get_setsolar_environment
(\
%job_hash);
356 return($error_code) if ($error_code);
358 my $solar_vars = $environments{$env_alias};
360 delete $ENV{$_} foreach (keys %ENV);
361 $ENV{$_} = $$solar_vars{$_} foreach (keys %$solar_vars);
363 if (defined $ENV{CWS_WORK_STAMP
}) {
364 print $ENV{CWS_WORK_STAMP
};
366 print $ENV{SOLARSRC
};
369 print "\nplatform: $ENV{INPATH} $^O";
370 print "\ndir: $job_hash{job_dir}\n";
371 print "job: $job_hash{job}\n";
372 chdir $job_hash{job_dir
};
374 my $job_string = $job_hash{job
} . ' > ' . $tmp_log_file . ' 2>&1';
375 $error_code = system($job_string);
376 # rename($tmp_log_file, $job_hash{log}) or system("mv", $tmp_log_file, $job_hash{log});
377 # delete $job_temp_files{$tmp_log_file};# = $job_hash{log};
379 rename($tmp_log_file, $job_hash{log}) or system("mv", $tmp_log_file, $job_hash{log});
380 delete $job_temp_files{$tmp_log_file};
383 print "Error code = $error_code\n\n";
385 print "Success!!\n\n";
390 sub get_setsolar_environment
{
391 my $job_hash = shift;
392 my $server_pid = $$job_hash{server_pid
};
393 my $setsolar_string = $$job_hash{setsolar_cmd
};
394 # Prepare the string for the client
395 $setsolar_string =~ s/\s-file\s\S+//g;
397 my $cmd_file = File
::Temp
::tmpnam
($ENV_BACKUP{TMP
});
398 my $tmp_log_file = File
::Temp
::tmpnam
($ENV_BACKUP{TMP
});
399 if (defined $$job_hash{updater
}) {
400 $ENV{UPDATER
} = $$job_hash{updater
};
402 undef $ENV{UPDATER
} if (defined $ENV{UPDATER
});
404 if (defined $$job_hash{source_root
}) {
405 $ENV{SOURCE_ROOT
} = $$job_hash{source_root
};
407 undef $ENV{SOURCE_ROOT
} if (defined $ENV{SOURCE_ROOT
});
409 $error_code = system("$setsolar_string -file $cmd_file");
410 store_env_hash
($cmd_file);
416 print STDERR
"\nERROR: $message\n";
420 my $ss_setenv_file = shift;#($$job_hash{server_pid}.$$job_hash{setsolar_cmd}, $cmd_file);
422 my $cmd_file = File
::Temp
::tmpnam
($ENV_BACKUP{TMP
});
423 my $env_vars_file = File
::Temp
::tmpnam
($ENV_BACKUP{TMP
});
424 print "$cmd_file $env_vars_file\n";
425 #get all env variables in $env_vars_file
426 open (COMMAND_FILE
, ">$cmd_file");
427 print COMMAND_FILE
"source $ss_setenv_file\n";
428 print COMMAND_FILE
"env > $env_vars_file\n";
430 system($ENV{SHELL
}, $cmd_file);
431 print_error
($?
) if ($?
);
432 unlink $cmd_file or system("rm -rf $cmd_file");
433 unlink $ss_setenv_file or system("rm -rf $ss_setenv_file");
435 open SOLARTABLE
, "<$env_vars_file" or die "canĀ“t open solarfile $env_vars_file";
436 while(<SOLARTABLE
>) {
440 $solar_vars{$`} = $';
443 unlink $env_vars_file or system("rm -rf $env_vars_file");
444 $environments{$env_alias} = \%solar_vars;