source: gs3-extensions/solr/trunk/src/perllib/solrserver.pm@ 29142

Last change on this file since 29142 was 29142, checked in by ak19, 10 years ago

Part of port from lucene3.3.0 to lucene4.7.2. Solr related. 1. Java and perl code changes for solr4.7.2; 2. Dr Bainbridge further fixed a bug in how the variable called running is set in solrserver.pm

File size: 14.3 KB
RevLine 
[24453]1###########################################################################
2#
3# solrserver.pm -- class for starting and stopping the Solr/jetty server
4# A component of the Greenstone digital library software
5# from the New Zealand Digital Library Project at the
6# University of Waikato, New Zealand.
7#
8# Copyright (C) 1999 New Zealand Digital Library Project
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program; if not, write to the Free Software
22# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23#
24###########################################################################
25
26
27package solrserver;
28
29use strict;
[24483]30#no strict 'refs';
[24453]31
32use solrutil;
33
34sub new {
35 my $class = shift(@_);
[24501]36 my ($build_dir) = @_;
[24453]37
[24484]38 my $self = { 'jetty_stop_key' => "greenstone-solr" };
[24453]39
[24501]40 $self->{'build_dir'} = $build_dir;
41
[24453]42 my $search_path = &solrutil::get_search_path();
43
44 my $server_jar = &util::filename_cat("lib","java","solr-jetty-server.jar");
45 my $full_server_jar = solrutil::locate_file($search_path,$server_jar);
46 $self->{'full_server_jar'} = $full_server_jar;
47
48 $self->{'jetty_explicitly_started'} = undef;
49
[24483]50 my $jetty_server_port = $ENV{'SOLR_JETTY_PORT'};
51 my $base_url = "http://localhost:$jetty_server_port/solr/";
52 my $admin_url = "http://localhost:$jetty_server_port/solr/admin/cores";
53
54 $self->{'base-url'} = $base_url;
55 $self->{'admin-url'} = $admin_url;
56
[24453]57 return bless $self, $class;
58}
59
[25899]60sub set_jetty_stop_key {
61 my $self = shift (@_);
62 my ($stop_key) = @_;
[24483]63
[25899]64 $self->{'jetty_stop_key'} = $stop_key if defined $stop_key;
65}
[24483]66
67sub _wget_service
68{
69 my $self = shift (@_);
70 my ($output_format,$url,$cgi_get_args) = @_;
71
72 my $full_url = $url;
73
74 $url .= "?$cgi_get_args" if (defined $cgi_get_args);
75
76 my $cmd = "wget -O - \"$url\" 2>&1";
77
78 my $preamble_output = "";
79 my $xml_output = "";
80 my $error_output = undef;
81
82 my $in_preamble = ($output_format eq "xml") ? 1 : 0;
83
[24501]84## print STDERR "**** wgetcmd = \n $cmd\n";
85
[24483]86 if (open(WIN,"$cmd |")) {
87
88 my $line;
89 while (defined ($line=<WIN>)) {
90
91 if ($line =~ m/ERROR \d+:/) {
92 chomp $line;
93 $error_output = $line;
94 last;
95 }
96 elsif ($line =~ m/failed: Connection refused/) {
97 chomp $line;
98 $error_output = $line;
99 last;
100 }
101 elsif ($in_preamble) {
102 if ($line =~ m/<.*>/) {
103 $in_preamble = 0;
104 }
105 else {
106 $preamble_output .= $line;
107 }
108 }
109
110 if (! $in_preamble) {
111 $xml_output .= $line;
112 }
113 }
114 close(WIN);
115
116 }
117 else {
118 $error_output = "Error: failed to run $cmd\n";
119 $error_output .= " $!\n";
120 }
121
[24643]122 my $output = { 'url' => $full_url,
123 'preamble' => $preamble_output,
[24483]124 'output' => $xml_output,
125 'error' => $error_output };
126
127 return $output;
128}
129
130
131sub _base_service
132{
133 my $self = shift (@_);
134 my ($cgi_get_args) = @_;
135
136 my $base_url = $self->{'base-url'};
137
138 return $self->_wget_service("html",$base_url,$cgi_get_args);
139}
140
141sub _admin_service
142{
143 my $self = shift (@_);
144 my ($cgi_get_args) = @_;
145
146 my $admin_url = $self->{'admin-url'};
147
148 return $self->_wget_service("xml",$admin_url,$cgi_get_args);
149}
150
151
152sub server_running
153{
154 my $self = shift @_;
155
156 my $output = $self->_base_service();
157
158 my $have_error = defined $output->{'error'};
159
[29142]160 my $running = ($have_error) ? 0 : 1;
[24483]161
162 return $running;
163}
164
165
166sub admin_ping_core
167{
168 my $self = shift @_;
169 my ($core) = @_;
170
171 my $cgi_get_args = "action=STATUS&core=$core";
172
173 my $ping_status = 1;
174
175 my $output = $self->_admin_service($cgi_get_args);
176
177 if (defined $output->{'error'}) {
178 # severe error, such as failing to connect to the server
179 $ping_status = 0;
180
181 my $url = $output->{'url'};
182 my $preamble = $output->{'preamble'};
183 my $error = $output->{'error'};
184
185 print STDERR "----\n";
186 print STDERR "Error: Failed to get XML response from:\n";
187 print STDERR " $url\n";
188 print STDERR "Output was:\n";
189 print STDERR $preamble if ($preamble ne "");
190 print STDERR "$error\n";
191 print STDERR "----\n";
192 }
193 else {
194
195 # If the collection doesn't exist yet, then there will be
196 # an empty element of the form:
197 # <lst name="collect-doc"/>
198 # where 'collect' is the actual name of the collection,
199 # such as demo
200
201 my $xml_output = $output->{'output'};
202
203 my $empty_element="<lst\\s+name=\"$core\"\\s*\\/>";
204
205 $ping_status = !($xml_output =~ m/$empty_element/s);
206 }
207
208 return $ping_status;
209}
210
[27858]211sub filtered_copy
212{
213 my $self = shift @_;
214
[28128]215 my $src_file = shift @_;
216 my $dst_file = shift @_;
217 my $re_substitutions = shift @_;
[27858]218
219 # $re_substitutions is a hashmap of the form: [re_key] => subst_str
[28128]220
[27858]221 my $content = "";
222
223 if (open(FIN,'<:utf8',$src_file)) {
224
225 my $line;
226 while (defined($line=<FIN>)) {
227 $content .= $line;
228 }
229 }
230
231 close(FIN);
232
233 # perform RE string substitutions
234 foreach my $re_key (keys %$re_substitutions) {
235
236 my $subst_str = $re_substitutions->{$re_key};
237
238 # Perform substitution of the form:
239 # $content =~ s/$re_key/$subst_str/g;
240 # but allow allow separator char (default '/')
241 # and flags (default 'g') to be parameterized
242
[28128]243 $content =~ s/$re_key/$subst_str/g;
[27858]244 }
245
246 if (open(FOUT, '>:utf8', $dst_file)) {
247 print FOUT $content;
248 close(FOUT);
249 }
250 else {
251 print STDERR "Error: Failed to open file '$dst_file' for writing.\n$!\n";
252 }
253}
254
255sub solr_xml_to_solr_xml_in
256{
257 my $self = shift @_;
[28182]258 my ($solr_xml_dir) = @_;
259
[27858]260 my $gsdl3home = $ENV{'GSDL3HOME'};
[28182]261
262 if (!defined $solr_xml_dir || !-d $solr_xml_dir) {
263 # if not passed in, use stored solr_live_home
264 $solr_xml_dir = $self->{'solr_live_home'};
265 }
266 my $solrxml_in = &util::filename_cat($solr_xml_dir, "solr.xml.in");
267 my $solrxml = &util::filename_cat($solr_xml_dir, "solr.xml");
[27858]268
[28128]269 my $gsdl3home_re = &util::filename_to_regex($gsdl3home);
270
271 my $replacement_map = { qr/$gsdl3home_re/ => "\@gsdl3home\@" };
272
[28182]273 $self->filtered_copy($solrxml,$solrxml_in,$replacement_map);
[27858]274}
275
276
277sub solr_xml_in_to_solr_xml
278{
279 my $self = shift @_;
[28182]280 my ($solr_xml_dir) = @_;
[27858]281
282 my $gsdl3home = $ENV{'GSDL3HOME'};
[28182]283 if (!defined $solr_xml_dir || !-d $solr_xml_dir) {
284 # if not passed in, use stored solr home
285 $solr_xml_dir = $self->{'solr_live_home'};
286 }
287 my $solrxml_in = &util::filename_cat($solr_xml_dir, "solr.xml.in");
288 my $solrxml = &util::filename_cat($solr_xml_dir, "solr.xml");
[27858]289
[28128]290 my $gsdl3home_re = &util::filename_to_regex($gsdl3home);
291
292 my $replacement_map = { qr/\@gsdl3home\@/ => $gsdl3home_re };
293
[28182]294 $self->filtered_copy($solrxml_in,$solrxml,$replacement_map);
[27858]295}
296
297
[25888]298# Some of the Solr CoreAdmin API calls available.
299# See http://wiki.apache.org/solr/CoreAdmin
[24483]300sub admin_reload_core
301{
302 my $self = shift @_;
303 my ($core) = @_;
304
305 my $cgi_get_args = "action=RELOAD&core=$core";
306
307 $self->_admin_service($cgi_get_args);
[27858]308
[24483]309}
310
[25888]311sub admin_rename_core
312{
313 my $self = shift @_;
314 my ($oldcore, $newcore) = @_;
[24483]315
[25888]316 my $cgi_get_args = "action=RENAME&core=$oldcore&other=$newcore";
317
318 $self->_admin_service($cgi_get_args);
[27858]319
[25888]320}
321
322sub admin_swap_core
323{
324 my $self = shift @_;
325 my ($oldcore, $newcore) = @_;
326
327 my $cgi_get_args = "action=SWAP&core=$oldcore&other=$newcore";
328
329 $self->_admin_service($cgi_get_args);
[27858]330
[25888]331}
332
333# The ALIAS action is not supported in our version of solr (despite it
334# being marked as experimental in the documentation for Core Admin)
335sub admin_alias_core
336{
337 my $self = shift @_;
338 my ($oldcore, $newcore) = @_;
339
340 my $cgi_get_args = "action=ALIAS&core=$oldcore&other=$newcore";
341
342 $self->_admin_service($cgi_get_args);
[27858]343
[25888]344}
345
[24483]346sub admin_create_core
347{
348 my $self = shift @_;
[25888]349 my ($core, $data_parent_dir) = @_; # data_parent_dir is optional, can be index_dir. Defaults to builddir if not provided
[24483]350
[24501]351 my ($ds_idx) = ($core =~ m/^.*-(.*?)$/);
[24483]352
353 my $cgi_get_args = "action=CREATE&name=$core";
354
355 my $collect_home = $ENV{'GSDLCOLLECTDIR'};
356 my $etc_dirname = &util::filename_cat($collect_home,"etc");
[25888]357
358 if(!defined $data_parent_dir) {
359 $data_parent_dir = $self->{'build_dir'};
360 }
361
362 my $idx_dirname = &util::filename_cat($data_parent_dir,$ds_idx); # "dataDir"
[24483]363
364 $cgi_get_args .= "&instanceDir=$etc_dirname";
365 $cgi_get_args .= "&dataDir=$idx_dirname";
366
367 $self->_admin_service($cgi_get_args);
[27858]368
[24483]369}
370
[25899]371# removes (unloads) core from the ext/solr/sorl.xml config file
[25888]372sub admin_unload_core
373{
374 my $self = shift @_;
[25889]375 my ($core, $delete) = @_;
[24483]376
[25888]377 my $cgi_get_args = "action=UNLOAD&core=$core"; # &deleteIndex=true from Solr3.3
[25889]378 if(defined $delete && $delete == 1) {
379 $cgi_get_args = $cgi_get_args."&deleteIndex=true";
380 }
[24483]381
[25888]382 $self->_admin_service($cgi_get_args);
[27858]383
[25888]384}
385
[24453]386sub start
387{
388 my $self = shift @_;
[25899]389 my ($verbosity) = @_;
390
391 $verbosity = 1 unless defined $verbosity;
[24453]392
393 my $solr_home = $ENV{'GEXT_SOLR'};
[28182]394 my $solr_live_home = &util::filename_cat($ENV{'GSDL3HOME'}, "ext", "solr");
[24453]395 my $jetty_stop_port = $ENV{'JETTY_STOP_PORT'};
396 my $jetty_server_port = $ENV{'SOLR_JETTY_PORT'};
397
398 chdir($solr_home);
[28182]399 #$self->{'solr_home'} = $solr_home;
400 $self->{'solr_live_home'} = $solr_live_home;
[24501]401## my $solr_etc = &util::filename_cat($solr_home,"etc");
[24453]402
403 my $server_props = "-DSTOP.PORT=$jetty_stop_port";
404 $server_props .= " -DSTOP.KEY=".$self->{'jetty_stop_key'};
[28182]405 #$server_props .= " -Dsolr.solr.home=$solr_home";
406$server_props .= " -Dsolr.solr.home=$solr_live_home";
[24453]407 my $full_server_jar = $self->{'full_server_jar'};
408
[29142]409 # https://wiki.apache.org/solr/SolrLogging
410 my $solr_slf4j = &util::filename_cat($solr_home, "lib", "ext");
411 my $solr_log4j = &util::filename_cat($solr_home, "conf", "log4j.properties");
412 my $server_java_cmd = "java -Dlog4j.configuration=file://$solr_log4j -classpath \"$solr_home/lib/java/*:$solr_slf4j/*\" $server_props -jar \"$full_server_jar\"";
[24453]413
414
[24483]415 my $server_status = "unknown";
[24453]416
[24486]417 if ($self->server_running()) {
[24483]418 $server_status = "already-running";
[24453]419 }
[24483]420 elsif (open(STARTIN,"$server_java_cmd 2>&1 |")) {
[24453]421
[25899]422 print STDERR "**** starting up solr jetty server with cmd start =\n $server_java_cmd\n" if ($verbosity > 1);
[24501]423
[24483]424 my $line;
425 while (defined($line=<STARTIN>)) {
426 # Scan through output until you see a line like:
427 # 2011-08-22 .. :INFO::Started [email protected]:8983
428 # which signifies that the server has started up and is
429 # "ready and listening"
[24453]430
[24483]431 if (($line =~ m/^(WARN|ERROR|SEVERE):/)
432 || ($line =~ m/^[0-9 :-]*(WARN|ERROR|SEVERE)::/)) {
433 print "Jetty startup: $line";
[24453]434 }
[24483]435
[29142]436 if ($line =~ m/WARN.*failed SocketConnector/) {
[24483]437 if ($line =~ m/Address already in use/) {
438 $server_status = "already-running";
439 }
440 else {
441 $server_status = "failed-to-start";
442 }
443 last;
[24453]444 }
[24483]445
[29142]446 if ($line =~ m/INFO.*Started SocketConnector/) {
[24483]447 $server_status = "explicitly-started";
448 last;
449 }
[24453]450 }
451 }
[24483]452 else {
453 print STDERR "Error: failed to start solr-jetty-server\n";
454 print STDERR "$!\n";
455 print STDERR "Command attempted was:\n";
456 print STDERR " $server_java_cmd\n";
457 print STDERR "run from directory:\n";
458 print STDERR " $solr_home\n";
459 print STDERR "----\n";
460
461 exit -1;
462 }
463
[24453]464 if ($server_status eq "explicitly-started") {
465 $self->{'jetty_explicitly_started'} = 1;
[24483]466 print "Jetty server ready and listening for connections on port";
467 print " $jetty_server_port\n";
[24453]468
469 # now we know the server is ready to accept connections, fork a
470 # child process that continues to listen to the output and
471 # prints out any lines that are not INFO lines
472
473 if (fork()==0) {
474 # child process
[24483]475
[24453]476 my $line;
477 while (defined ($line = <STARTIN>)) {
478
479# if (($line =~ m/^(WARN|ERROR|SEVERE):/)
480# || ($line =~ m/^[0-9 :-]*(WARN|ERROR|SEVERE)::/)) {
481# print "Jetty $line";
482# }
483
484 # skip info lines
485 next if ($line =~ m/^INFO:/);
486 next if ($line =~ m/^[0-9 :-]*INFO::/);
487 next if ($line =~ m/^\d{2}\/\d{2}\/\d{4}\s+/);
488 next if ($line =~ m/^\d{4}-\d{2}-\d{2}\s+/);
489
490## next if ($line =~ m/^\s*\w+{.*}/);
491
492 # if here, then some non-trival message has been logged
493 print "Jetty/Solr processing: $line";
494 }
495 close(STARTIN);
496
497 # And now stop nicely
498 exit 0;
499 }
500 # otherwise let the parent continue on
501 }
502 elsif ($server_status eq "already-running") {
[24483]503 print STDERR "Using existing server detected on port $jetty_server_port\n";
[24453]504 $self->{'jetty_explicitly_started'} = 0;
505 }
[24483]506 elsif ($server_status eq "failed-to-start") {
507 print STDERR "Started Solr/Jetty web server on port $jetty_server_port";
508 print STDERR ", but encountered an initialization error\n";
[24453]509 exit -1;
510 }
511
512}
513
514sub explicitly_started
515{
516 my $self = shift @_;
517
518 return $self->{'jetty_explicitly_started'};
519}
520
521sub stop
522{
523 my $self = shift @_;
524 my ($options) = @_;
525
526 my $solr_home = $ENV{'GEXT_SOLR'};
527
528 chdir($solr_home);
529
530 # defaults
531 my $do_wait = 1;
532 my $output_verbosity = 1;
533
534 if (defined $options) {
535 if (defined $options->{'do_wait'}) {
536 $do_wait = $options->{'do_wait'};
537 }
538 if (defined $options->{'output_verbosity'}) {
539 $output_verbosity = $options->{'output_verbosity'};
540 }
541 }
542
543 my $full_server_jar = $self->{'full_server_jar'};
544 my $jetty_stop_port = $ENV{'JETTY_STOP_PORT'};
545
546 my $server_props = "-DSTOP.PORT=$jetty_stop_port";
547 $server_props .= " -DSTOP.KEY=".$self->{'jetty_stop_key'};
548 my $server_java_cmd = "java $server_props -jar \"$full_server_jar\" --stop";
[24483]549
[25899]550 print STDERR "**** java server stop cmd:\n $server_java_cmd\n" if ($output_verbosity>1);
[24483]551
[24453]552 if (open(STOPIN,"$server_java_cmd 2>&1 |")) {
553
554 my $line;
555 while (defined($line=<STOPIN>)) {
556 print "Jetty shutdown: $line" if ($output_verbosity>1);
557 }
558 close(STOPIN);
559
560 if ($do_wait) {
561 wait(); # let the child process finish
562 }
563
564 if ($output_verbosity>0) {
565 print "Jetty server shutdown\n";
566 }
567 }
568 else {
569 print STDERR "Error: failed to stop solr-jetty-server\n";
[24483]570 print STDERR "$!\n";
[24453]571 print STDERR "Command attempted was:\n";
572 print STDERR " $server_java_cmd\n";
573 print STDERR "run from directory:\n";
574 print STDERR " $solr_home\n";
575 print STDERR "----\n";
576
577 exit -2;
578 }
579}
580
581
582
5831;
Note: See TracBrowser for help on using the repository browser.