Merge remote-tracking branch 'origin/new/bug_5533'
[koha.git] / misc / migration_tools / rebuild_zebra.pl
1 #!/usr/bin/perl
2
3 use strict;
4 #use warnings; FIXME - Bug 2505
5
6 use C4::Context;
7 use Getopt::Long;
8 use File::Temp qw/ tempdir /;
9 use File::Path;
10 use C4::Biblio;
11 use C4::AuthoritiesMarc;
12 use C4::Items;
13
14
15 # script that checks zebradir structure & create directories & mandatory files if needed
16 #
17 #
18
19 $|=1; # flushes output
20 # If the cron job starts us in an unreadable dir, we will break without
21 # this.
22 chdir $ENV{HOME} if (!(-r '.'));
23 my $directory;
24 my $nosanitize;
25 my $skip_export;
26 my $keep_export;
27 my $reset;
28 my $biblios;
29 my $authorities;
30 my $noxml;
31 my $noshadow;
32 my $do_munge;
33 my $want_help;
34 my $as_xml;
35 my $process_zebraqueue;
36 my $do_not_clear_zebraqueue;
37 my $verbose_logging;
38 my $zebraidx_log_opt = " -v none,fatal,warn ";
39 my $result = GetOptions(
40     'd:s'           => \$directory,
41     'r|reset'       => \$reset,
42     's'             => \$skip_export,
43     'k'             => \$keep_export,
44     'nosanitize'    => \$nosanitize,
45     'b'             => \$biblios,
46     'noxml'         => \$noxml,
47     'w'             => \$noshadow,
48     'munge-config'  => \$do_munge,
49     'a'             => \$authorities,
50     'h|help'        => \$want_help,
51         'x'                             => \$as_xml,
52     'y'             => \$do_not_clear_zebraqueue,
53     'z'             => \$process_zebraqueue,
54     'v'             => \$verbose_logging,
55 );
56
57
58 if (not $result or $want_help) {
59     print_usage();
60     exit 0;
61 }
62
63 if (not $biblios and not $authorities) {
64     my $msg = "Must specify -b or -a to reindex bibs or authorities\n";
65     $msg   .= "Please do '$0 --help' to see usage.\n";
66     die $msg;
67 }
68
69 if ($authorities and $as_xml) {
70     my $msg = "Cannot specify both -a and -x\n";
71     $msg   .= "Please do '$0 --help' to see usage.\n";
72     die $msg;
73 }
74
75 if ( !$as_xml and $nosanitize ) {
76     my $msg = "Cannot specify both -no_xml and -nosanitize\n";
77     $msg   .= "Please do '$0 --help' to see usage.\n";
78     die $msg;
79 }
80
81 if ($process_zebraqueue and ($skip_export or $reset)) {
82     my $msg = "Cannot specify -r or -s if -z is specified\n";
83     $msg   .= "Please do '$0 --help' to see usage.\n";
84     die $msg;
85 }
86
87 if ($process_zebraqueue and $do_not_clear_zebraqueue) {
88     my $msg = "Cannot specify both -y and -z\n";
89     $msg   .= "Please do '$0 --help' to see usage.\n";
90     die $msg;
91 }
92
93 if ($noshadow) {
94     $noshadow = ' -n ';
95 }
96
97 #  -v is for verbose, which seems backwards here because of how logging is set
98 #    on the CLI of zebraidx.  It works this way.  The default is to not log much
99 if ($verbose_logging) {
100     $zebraidx_log_opt = '';
101 }
102
103 my $use_tempdir = 0;
104 unless ($directory) {
105     $use_tempdir = 1;
106     $directory = tempdir(CLEANUP => ($keep_export ? 0 : 1));
107
108
109
110 my $biblioserverdir = C4::Context->zebraconfig('biblioserver')->{directory};
111 my $authorityserverdir = C4::Context->zebraconfig('authorityserver')->{directory};
112
113 my $kohadir = C4::Context->config('intranetdir');
114 my $dbh = C4::Context->dbh;
115 my ($biblionumbertagfield,$biblionumbertagsubfield) = &GetMarcFromKohaField("biblio.biblionumber","");
116 my ($biblioitemnumbertagfield,$biblioitemnumbertagsubfield) = &GetMarcFromKohaField("biblioitems.biblioitemnumber","");
117
118 if ( $verbose_logging ) {
119     print "Zebra configuration information\n";
120     print "================================\n";
121     print "Zebra biblio directory      = $biblioserverdir\n";
122     print "Zebra authorities directory = $authorityserverdir\n";
123     print "Koha directory              = $kohadir\n";
124     print "BIBLIONUMBER in :     $biblionumbertagfield\$$biblionumbertagsubfield\n";
125     print "BIBLIOITEMNUMBER in : $biblioitemnumbertagfield\$$biblioitemnumbertagsubfield\n";
126     print "================================\n";
127 }
128
129 if ($do_munge) {
130     munge_config();
131 }
132
133 if ($authorities) {
134     index_records('authority', $directory, $skip_export, $process_zebraqueue, $as_xml, $noxml, $nosanitize, $do_not_clear_zebraqueue, $verbose_logging, $zebraidx_log_opt, $authorityserverdir);
135 } else {
136     print "skipping authorities\n" if ( $verbose_logging );
137 }
138
139 if ($biblios) {
140     index_records('biblio', $directory, $skip_export, $process_zebraqueue, $as_xml, $noxml, $nosanitize, $do_not_clear_zebraqueue, $verbose_logging, $zebraidx_log_opt, $biblioserverdir);
141 } else {
142     print "skipping biblios\n" if ( $verbose_logging );
143 }
144
145
146 if ( $verbose_logging ) {
147     print "====================\n";
148     print "CLEANING\n";
149     print "====================\n";
150 }
151 if ($keep_export) {
152     print "NOTHING cleaned : the export $directory has been kept.\n";
153     print "You can re-run this script with the -s ";
154     if ($use_tempdir) {
155         print " and -d $directory parameters";
156     } else {
157         print "parameter";
158     }
159     print "\n";
160     print "if you just want to rebuild zebra after changing the record.abs\n";
161     print "or another zebra config file\n";
162 } else {
163     unless ($use_tempdir) {
164         # if we're using a temporary directory
165         # created by File::Temp, it will be removed
166         # automatically.
167         rmtree($directory, 0, 1);
168         print "directory $directory deleted\n";
169     }
170 }
171
172 # This checks to see if the zebra directories exist under the provided path.
173 # If they don't, then zebra is likely to spit the dummy. This returns true
174 # if the directories had to be created, false otherwise.
175 sub check_zebra_dirs {
176         my ($base) = shift() . '/';
177         my $needed_repairing = 0;
178         my @dirs = ( '', 'key', 'register', 'shadow', 'tmp' );
179         foreach my $dir (@dirs) {
180                 my $bdir = $base . $dir;
181         if (! -d $bdir) {
182                 $needed_repairing = 1;
183                 mkdir $bdir || die "Unable to create '$bdir': $!\n";
184                 print "$0: needed to create '$bdir'\n";
185         }
186     }
187     return $needed_repairing;
188 }       # ----------  end of subroutine check_zebra_dirs  ----------
189
190 sub index_records {
191     my ($record_type, $directory, $skip_export, $process_zebraqueue, $as_xml, $noxml, $nosanitize, $do_not_clear_zebraqueue, $verbose_logging, $zebraidx_log_opt, $server_dir) = @_;
192
193     my $num_records_exported = 0;
194     my $records_deleted;
195     my $need_reset = check_zebra_dirs($server_dir);
196     if ($need_reset) {
197         print "$0: found broken zebra server directories: forcing a rebuild\n";
198         $reset = 1;
199     }
200     if ($skip_export && $verbose_logging) {
201         print "====================\n";
202         print "SKIPPING $record_type export\n";
203         print "====================\n";
204     } else {
205         if ( $verbose_logging ) {
206             print "====================\n";
207             print "exporting $record_type\n";
208             print "====================\n";
209         }
210         mkdir "$directory" unless (-d $directory);
211         mkdir "$directory/$record_type" unless (-d "$directory/$record_type");
212         if ($process_zebraqueue) {
213             my $entries = select_zebraqueue_records($record_type, 'deleted');
214             mkdir "$directory/del_$record_type" unless (-d "$directory/del_$record_type");
215             $records_deleted = generate_deleted_marc_records($record_type, $entries, "$directory/del_$record_type", $as_xml);
216             mark_zebraqueue_batch_done($entries);
217             $entries = select_zebraqueue_records($record_type, 'updated');
218             mkdir "$directory/upd_$record_type" unless (-d "$directory/upd_$record_type");
219             $num_records_exported = export_marc_records_from_list($record_type, 
220                                                                   $entries, "$directory/upd_$record_type", $as_xml, $noxml, $records_deleted);
221             mark_zebraqueue_batch_done($entries);
222         } else {
223             my $sth = select_all_records($record_type);
224             $num_records_exported = export_marc_records_from_sth($record_type, $sth, "$directory/$record_type", $as_xml, $noxml, $nosanitize);
225             unless ($do_not_clear_zebraqueue) {
226                 mark_all_zebraqueue_done($record_type);
227             }
228         }
229     }
230     
231     #
232     # and reindexing everything
233     #
234     if ( $verbose_logging ) {
235         print "====================\n";
236         print "REINDEXING zebra\n";
237         print "====================\n";
238     }
239         my $record_fmt = ($as_xml) ? 'marcxml' : 'iso2709' ;
240     if ($process_zebraqueue) {
241         do_indexing($record_type, 'delete', "$directory/del_$record_type", $reset, $noshadow, $record_fmt, $zebraidx_log_opt) 
242             if %$records_deleted;
243         do_indexing($record_type, 'update', "$directory/upd_$record_type", $reset, $noshadow, $record_fmt, $zebraidx_log_opt)
244             if $num_records_exported;
245     } else {
246         do_indexing($record_type, 'update', "$directory/$record_type", $reset, $noshadow, $record_fmt, $zebraidx_log_opt)
247             if ($num_records_exported or $skip_export);
248     }
249 }
250
251
252 sub select_zebraqueue_records {
253     my ($record_type, $update_type) = @_;
254
255     my $server = ($record_type eq 'biblio') ? 'biblioserver' : 'authorityserver';
256     my $op = ($update_type eq 'deleted') ? 'recordDelete' : 'specialUpdate';
257
258     my $sth = $dbh->prepare("SELECT id, biblio_auth_number 
259                              FROM zebraqueue
260                              WHERE server = ?
261                              AND   operation = ?
262                              AND   done = 0
263                              ORDER BY id DESC");
264     $sth->execute($server, $op);
265     my $entries = $sth->fetchall_arrayref({});
266 }
267
268 sub mark_all_zebraqueue_done {
269     my ($record_type) = @_;
270
271     my $server = ($record_type eq 'biblio') ? 'biblioserver' : 'authorityserver';
272
273     my $sth = $dbh->prepare("UPDATE zebraqueue SET done = 1
274                              WHERE server = ?
275                              AND done = 0");
276     $sth->execute($server);
277 }
278
279 sub mark_zebraqueue_batch_done {
280     my ($entries) = @_;
281
282     $dbh->{AutoCommit} = 0;
283     my $sth = $dbh->prepare("UPDATE zebraqueue SET done = 1 WHERE id = ?");
284     $dbh->commit();
285     foreach my $id (map { $_->{id} } @$entries) {
286         $sth->execute($id);
287     }
288     $dbh->{AutoCommit} = 1;
289 }
290
291 sub select_all_records {
292     my $record_type = shift;
293     return ($record_type eq 'biblio') ? select_all_biblios() : select_all_authorities();
294 }
295
296 sub select_all_authorities {
297     my $sth = $dbh->prepare("SELECT authid FROM auth_header");
298     $sth->execute();
299     return $sth;
300 }
301
302 sub select_all_biblios {
303     my $sth = $dbh->prepare("SELECT biblionumber FROM biblioitems ORDER BY biblionumber");
304     $sth->execute();
305     return $sth;
306 }
307
308 sub export_marc_records_from_sth {
309     my ($record_type, $sth, $directory, $as_xml, $noxml, $nosanitize) = @_;
310
311     my $num_exported = 0;
312     open (OUT, ">:utf8 ", "$directory/exported_records") or die $!;
313     my $i = 0;
314     my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField("items.itemnumber",'');
315     while (my ($record_number) = $sth->fetchrow_array) {
316         print "." if ( $verbose_logging );
317         print "\r$i" unless ($i++ %100 or !$verbose_logging);
318         if ( $nosanitize ) {
319             my $marcxml = $record_type eq 'biblio'
320                           ? GetXmlBiblio( $record_number )
321                           : GetAuthorityXML( $record_number );
322             if ($record_type eq 'biblio'){
323                 my @items = GetItemsInfo($record_number);
324                 if (@items){
325                     my $record = MARC::Record->new;
326                     $record->encoding('UTF-8');
327                     my @itemsrecord;
328                     foreach my $item (@items){
329                         my $record = Item2Marc($item, $record_number);                        
330                         push @itemsrecord, $record->field($itemtag);
331                     }
332                     $record->insert_fields_ordered(@itemsrecord);
333                     my $itemsxml = $record->as_xml_record();
334                     $marcxml =
335                         substr($marcxml, 0, length($marcxml)-10) .
336                         substr($itemsxml, index($itemsxml, "</leader>\n", 0) + 10);
337                 }
338             }
339             if ( $marcxml ) {
340                 print OUT $marcxml if $marcxml;
341                 $num_exported++;
342             }
343             next;
344         }
345         my ($marc) = get_corrected_marc_record($record_type, $record_number, $noxml);
346         if (defined $marc) {
347             # FIXME - when more than one record is exported and $as_xml is true,
348             # the output file is not valid XML - it's just multiple <record> elements
349             # strung together with no single root element.  zebraidx doesn't seem
350             # to care, though, at least if you're using the GRS-1 filter.  It does
351             # care if you're using the DOM filter, which requires valid XML file(s).
352             eval {
353                 print OUT ($as_xml) ? $marc->as_xml_record(C4::Context->preference('marcflavour')) : $marc->as_usmarc();
354                 $num_exported++;
355             };
356             if ($@) {
357               warn "Error exporting record $record_number ($record_type) ".($noxml ? "not XML" : "XML");
358             }
359         }
360     }
361     print "\nRecords exported: $num_exported\n" if ( $verbose_logging );
362     close OUT;
363     return $num_exported;
364 }
365
366 sub export_marc_records_from_list {
367     my ($record_type, $entries, $directory, $as_xml, $noxml, $records_deleted) = @_;
368
369     my $num_exported = 0;
370     open (OUT, ">:utf8 ", "$directory/exported_records") or die $!;
371     my $i = 0;
372
373     # Skip any deleted records. We check for this anyway, but this reduces error spam
374     my %found = %$records_deleted;
375     foreach my $record_number ( map { $_->{biblio_auth_number} }
376                                 grep { !$found{ $_->{biblio_auth_number} }++ }
377                                 @$entries ) {
378         print "." if ( $verbose_logging );
379         print "\r$i" unless ($i++ %100 or !$verbose_logging);
380         my ($marc) = get_corrected_marc_record($record_type, $record_number, $noxml);
381         if (defined $marc) {
382             # FIXME - when more than one record is exported and $as_xml is true,
383             # the output file is not valid XML - it's just multiple <record> elements
384             # strung together with no single root element.  zebraidx doesn't seem
385             # to care, though, at least if you're using the GRS-1 filter.  It does
386             # care if you're using the DOM filter, which requires valid XML file(s).
387             print OUT ($as_xml) ? $marc->as_xml_record(C4::Context->preference('marcflavour')) : $marc->as_usmarc();
388             $num_exported++;
389         }
390     }
391     print "\nRecords exported: $num_exported\n" if ( $verbose_logging );
392     close OUT;
393     return $num_exported;
394 }
395
396 sub generate_deleted_marc_records {
397     my ($record_type, $entries, $directory, $as_xml) = @_;
398
399     my $records_deleted = {};
400     open (OUT, ">:utf8 ", "$directory/exported_records") or die $!;
401     my $i = 0;
402     foreach my $record_number (map { $_->{biblio_auth_number} } @$entries ) {
403         print "\r$i" unless ($i++ %100 or !$verbose_logging);
404         print "." if ( $verbose_logging );
405
406         my $marc = MARC::Record->new();
407         if ($record_type eq 'biblio') {
408             fix_biblio_ids($marc, $record_number, $record_number);
409         } else {
410             fix_authority_id($marc, $record_number);
411         }
412         if (C4::Context->preference("marcflavour") eq "UNIMARC") {
413             fix_unimarc_100($marc);
414         }
415
416         print OUT ($as_xml) ? $marc->as_xml_record(C4::Context->preference("marcflavour")) : $marc->as_usmarc();
417
418         $records_deleted->{$record_number} = 1;
419     }
420     print "\nRecords exported: $i\n" if ( $verbose_logging );
421     close OUT;
422     return $records_deleted;
423     
424
425 }
426
427 sub get_corrected_marc_record {
428     my ($record_type, $record_number, $noxml) = @_;
429
430     my $marc = get_raw_marc_record($record_type, $record_number, $noxml); 
431
432     if (defined $marc) {
433         fix_leader($marc);
434         if ($record_type eq 'authority') {
435             fix_authority_id($marc, $record_number);
436         }
437         if (C4::Context->preference("marcflavour") eq "UNIMARC") {
438             fix_unimarc_100($marc);
439         }
440     }
441
442     return $marc;
443 }
444
445 sub get_raw_marc_record {
446     my ($record_type, $record_number, $noxml) = @_;
447   
448     my $marc; 
449     if ($record_type eq 'biblio') {
450         if ($noxml) {
451             my $fetch_sth = $dbh->prepare_cached("SELECT marc FROM biblioitems WHERE biblionumber = ?");
452             $fetch_sth->execute($record_number);
453             if (my ($blob) = $fetch_sth->fetchrow_array) {
454                 $marc = MARC::Record->new_from_usmarc($blob);
455                 unless ($marc) {
456                     warn "error creating MARC::Record from $blob";
457                 }
458             }
459             # failure to find a bib is not a problem -
460             # a delete could have been done before
461             # trying to process a record update
462
463             $fetch_sth->finish();
464             return unless $marc;
465         } else {
466             eval { $marc = GetMarcBiblio($record_number, 1); };
467             if ($@ || !$marc) {
468                 # here we do warn since catching an exception
469                 # means that the bib was found but failed
470                 # to be parsed
471                 warn "error retrieving biblio $record_number";
472                 return;
473             }
474         }
475     } else {
476         eval { $marc = GetAuthority($record_number); };
477         if ($@) {
478             warn "error retrieving authority $record_number";
479             return;
480         }
481     }
482     return $marc;
483 }
484
485 sub fix_leader {
486     # FIXME - this routine is suspect
487     # It blanks the Leader/00-05 and Leader/12-16 to
488     # force them to be recalculated correct when
489     # the $marc->as_usmarc() or $marc->as_xml() is called.
490     # But why is this necessary?  It would be a serious bug
491     # in MARC::Record (definitely) and MARC::File::XML (arguably) 
492     # if they are emitting incorrect leader values.
493     my $marc = shift;
494
495     my $leader = $marc->leader;
496     substr($leader,  0, 5) = '     ';
497     substr($leader, 10, 7) = '22     ';
498     $marc->leader(substr($leader, 0, 24));
499 }
500
501 sub fix_biblio_ids {
502     # FIXME - it is essential to ensure that the biblionumber is present,
503     #         otherwise, Zebra will choke on the record.  However, this
504     #         logic belongs in the relevant C4::Biblio APIs.
505     my $marc = shift;
506     my $biblionumber = shift;
507     my $biblioitemnumber;
508     if (@_) {
509         $biblioitemnumber = shift;
510     } else {    
511         my $sth = $dbh->prepare(
512             "SELECT biblioitemnumber FROM biblioitems WHERE biblionumber=?");
513         $sth->execute($biblionumber);
514         ($biblioitemnumber) = $sth->fetchrow_array;
515         $sth->finish;
516         unless ($biblioitemnumber) {
517             warn "failed to get biblioitemnumber for biblio $biblionumber";
518             return 0;
519         }
520     }
521
522     # FIXME - this is cheating on two levels
523     # 1. C4::Biblio::_koha_marc_update_bib_ids is meant to be an internal function
524     # 2. Making sure that the biblionumber and biblioitemnumber are correct and
525     #    present in the MARC::Record object ought to be part of GetMarcBiblio.
526     #
527     # On the other hand, this better for now than what rebuild_zebra.pl used to
528     # do, which was duplicate the code for inserting the biblionumber 
529     # and biblioitemnumber
530     C4::Biblio::_koha_marc_update_bib_ids($marc, '', $biblionumber, $biblioitemnumber);
531
532     return 1;
533 }
534
535 sub fix_authority_id {
536     # FIXME - as with fix_biblio_ids, the authid must be present
537     #         for Zebra's sake.  However, this really belongs
538     #         in C4::AuthoritiesMarc.
539     my ($marc, $authid) = @_;
540     unless ($marc->field('001') and $marc->field('001')->data() eq $authid){
541         $marc->delete_field($marc->field('001'));
542         $marc->insert_fields_ordered(MARC::Field->new('001',$authid));
543     }
544 }
545
546 sub fix_unimarc_100 {
547     # FIXME - again, if this is necessary, it belongs in C4::AuthoritiesMarc.
548     my $marc = shift;
549
550     my $string;
551     if ( length($marc->subfield( 100, "a" )) == 35 ) {
552         $string = $marc->subfield( 100, "a" );
553         my $f100 = $marc->field(100);
554         $marc->delete_field($f100);
555     }
556     else {
557         $string = POSIX::strftime( "%Y%m%d", localtime );
558         $string =~ s/\-//g;
559         $string = sprintf( "%-*s", 35, $string );
560     }
561     substr( $string, 22, 6, "frey50" );
562     unless ( length($marc->subfield( 100, "a" )) == 35 ) {
563         $marc->delete_field($marc->field(100));
564         $marc->insert_grouped_field(MARC::Field->new( 100, "", "", "a" => $string ));
565     }
566 }
567
568 sub do_indexing {
569     my ($record_type, $op, $record_dir, $reset_index, $noshadow, $record_format, $zebraidx_log_opt) = @_;
570
571     my $zebra_server  = ($record_type eq 'biblio') ? 'biblioserver' : 'authorityserver';
572     my $zebra_db_name = ($record_type eq 'biblio') ? 'biblios' : 'authorities';
573     my $zebra_config  = C4::Context->zebraconfig($zebra_server)->{'config'};
574     my $zebra_db_dir  = C4::Context->zebraconfig($zebra_server)->{'directory'};
575
576     system("zebraidx -c $zebra_config $zebraidx_log_opt -g $record_format -d $zebra_db_name init") if $reset_index;
577     system("zebraidx -c $zebra_config $zebraidx_log_opt $noshadow -g $record_format -d $zebra_db_name $op $record_dir");
578     system("zebraidx -c $zebra_config $zebraidx_log_opt -g $record_format -d $zebra_db_name commit") unless $noshadow;
579
580 }
581
582 sub print_usage {
583     print <<_USAGE_;
584 $0: reindex MARC bibs and/or authorities in Zebra.
585
586 Use this batch job to reindex all biblio or authority
587 records in your Koha database.  This job is useful
588 only if you are using Zebra; if you are using the 'NoZebra'
589 mode, this job should not be used.
590
591 Parameters:
592     -b                      index bibliographic records
593
594     -a                      index authority records
595
596     -z                      select only updated and deleted
597                             records marked in the zebraqueue
598                             table.  Cannot be used with -r
599                             or -s.
600
601     -r                      clear Zebra index before
602                             adding records to index
603
604     -d                      Temporary directory for indexing.
605                             If not specified, one is automatically
606                             created.  The export directory
607                             is automatically deleted unless
608                             you supply the -k switch.
609
610     -k                      Do not delete export directory.
611
612     -s                      Skip export.  Used if you have
613                             already exported the records 
614                             in a previous run.
615
616     -noxml                  index from ISO MARC blob
617                             instead of MARC XML.  This
618                             option is recommended only
619                             for advanced user.
620
621     -x                      export and index as xml instead of is02709 (biblios only).
622                             use this if you might have records > 99,999 chars,
623                                                         
624     -nosanitize             export biblio/authority records directly from DB marcxml
625                             field without sanitizing records. It speed up
626                             dump process but could fail if DB contains badly
627                             encoded records. Works only with -x,
628
629     -w                      skip shadow indexing for this batch
630
631     -y                      do NOT clear zebraqueue after indexing; normally,
632                             after doing batch indexing, zebraqueue should be
633                             marked done for the affected record type(s) so that
634                             a running zebraqueue_daemon doesn't try to reindex
635                             the same records - specify -y to override this.  
636                             Cannot be used with -z.
637
638     -v                      increase the amount of logging.  Normally only 
639                             warnings and errors from the indexing are shown.
640
641     -munge-config           Deprecated option to try
642                             to fix Zebra config files.
643     --help or -h            show this message.
644 _USAGE_
645 }
646
647 # FIXME: the following routines are deprecated and 
648 # will be removed once it is determined whether
649 # a script to fix Zebra configuration files is 
650 # actually needed.
651 sub munge_config {
652 #
653 # creating zebra-biblios.cfg depending on system
654 #
655
656 # getting zebraidx directory
657 my $zebraidxdir;
658 foreach (qw(/usr/local/bin/zebraidx
659         /opt/bin/zebraidx
660         /usr/bin/zebraidx
661         )) {
662     if ( -f $_ ) {
663         $zebraidxdir=$_;
664     }
665 }
666
667 unless ($zebraidxdir) {
668     print qq|
669     ERROR: could not find zebraidx directory
670     ERROR: Either zebra is not installed,
671     ERROR: or it's in a directory I don't checked.
672     ERROR: do a which zebraidx and edit this file to add the result you get
673 |;
674     exit;
675 }
676 $zebraidxdir =~ s/\/bin\/.*//;
677 print "Info : zebra is in $zebraidxdir \n";
678
679 # getting modules directory
680 my $modulesdir;
681 foreach (qw(/usr/local/lib/idzebra-2.0/modules/mod-grs-xml.so
682             /usr/local/lib/idzebra/modules/mod-grs-xml.so
683             /usr/lib/idzebra/modules/mod-grs-xml.so
684             /usr/lib/idzebra-2.0/modules/mod-grs-xml.so
685         )) {
686     if ( -f $_ ) {
687         $modulesdir=$_;
688     }
689 }
690
691 unless ($modulesdir) {
692     print qq|
693     ERROR: could not find mod-grs-xml.so directory
694     ERROR: Either zebra is not properly compiled (libxml2 is not setup and you don t have mod-grs-xml.so,
695     ERROR: or it's in a directory I don't checked.
696     ERROR: find where mod-grs-xml.so is and edit this file to add the result you get
697 |;
698     exit;
699 }
700 $modulesdir =~ s/\/modules\/.*//;
701 print "Info: zebra modules dir : $modulesdir\n";
702
703 # getting tab directory
704 my $tabdir;
705 foreach (qw(/usr/local/share/idzebra/tab/explain.att
706             /usr/local/share/idzebra-2.0/tab/explain.att
707             /usr/share/idzebra/tab/explain.att
708             /usr/share/idzebra-2.0/tab/explain.att
709         )) {
710     if ( -f $_ ) {
711         $tabdir=$_;
712     }
713 }
714
715 unless ($tabdir) {
716     print qq|
717     ERROR: could not find explain.att directory
718     ERROR: Either zebra is not properly compiled,
719     ERROR: or it's in a directory I don't checked.
720     ERROR: find where explain.att is and edit this file to add the result you get
721 |;
722     exit;
723 }
724 $tabdir =~ s/\/tab\/.*//;
725 print "Info: tab dir : $tabdir\n";
726
727 #
728 # AUTHORITIES creating directory structure
729 #
730 my $created_dir_or_file = 0;
731 if ($authorities) {
732     if ( $verbose_logging ) {
733         print "====================\n";
734         print "checking directories & files for authorities\n";
735         print "====================\n";
736     }
737     unless (-d "$authorityserverdir") {
738         system("mkdir -p $authorityserverdir");
739         print "Info: created $authorityserverdir\n";
740         $created_dir_or_file++;
741     }
742     unless (-d "$authorityserverdir/lock") {
743         mkdir "$authorityserverdir/lock";
744         print "Info: created $authorityserverdir/lock\n";
745         $created_dir_or_file++;
746     }
747     unless (-d "$authorityserverdir/register") {
748         mkdir "$authorityserverdir/register";
749         print "Info: created $authorityserverdir/register\n";
750         $created_dir_or_file++;
751     }
752     unless (-d "$authorityserverdir/shadow") {
753         mkdir "$authorityserverdir/shadow";
754         print "Info: created $authorityserverdir/shadow\n";
755         $created_dir_or_file++;
756     }
757     unless (-d "$authorityserverdir/tab") {
758         mkdir "$authorityserverdir/tab";
759         print "Info: created $authorityserverdir/tab\n";
760         $created_dir_or_file++;
761     }
762     unless (-d "$authorityserverdir/key") {
763         mkdir "$authorityserverdir/key";
764         print "Info: created $authorityserverdir/key\n";
765         $created_dir_or_file++;
766     }
767     
768     unless (-d "$authorityserverdir/etc") {
769         mkdir "$authorityserverdir/etc";
770         print "Info: created $authorityserverdir/etc\n";
771         $created_dir_or_file++;
772     }
773     
774     #
775     # AUTHORITIES : copying mandatory files
776     #
777     # the record model, depending on marc flavour
778     unless (-f "$authorityserverdir/tab/record.abs") {
779         if (C4::Context->preference("marcflavour") eq "UNIMARC") {
780             system("cp -f $kohadir/etc/zebradb/marc_defs/unimarc/authorities/record.abs $authorityserverdir/tab/record.abs");
781             print "Info: copied record.abs for UNIMARC\n";
782         } else {
783             system("cp -f $kohadir/etc/zebradb/marc_defs/marc21/authorities/record.abs $authorityserverdir/tab/record.abs");
784             print "Info: copied record.abs for USMARC\n";
785         }
786         $created_dir_or_file++;
787     }
788     unless (-f "$authorityserverdir/tab/sort-string-utf.chr") {
789         system("cp -f $kohadir/etc/zebradb/lang_defs/fr/sort-string-utf.chr $authorityserverdir/tab/sort-string-utf.chr");
790         print "Info: copied sort-string-utf.chr\n";
791         $created_dir_or_file++;
792     }
793     unless (-f "$authorityserverdir/tab/word-phrase-utf.chr") {
794         system("cp -f $kohadir/etc/zebradb/lang_defs/fr/sort-string-utf.chr $authorityserverdir/tab/word-phrase-utf.chr");
795         print "Info: copied word-phase-utf.chr\n";
796         $created_dir_or_file++;
797     }
798     unless (-f "$authorityserverdir/tab/auth1.att") {
799         system("cp -f $kohadir/etc/zebradb/authorities/etc/bib1.att $authorityserverdir/tab/auth1.att");
800         print "Info: copied auth1.att\n";
801         $created_dir_or_file++;
802     }
803     unless (-f "$authorityserverdir/tab/default.idx") {
804         system("cp -f $kohadir/etc/zebradb/etc/default.idx $authorityserverdir/tab/default.idx");
805         print "Info: copied default.idx\n";
806         $created_dir_or_file++;
807     }
808     
809     unless (-f "$authorityserverdir/etc/ccl.properties") {
810 #         system("cp -f $kohadir/etc/zebradb/ccl.properties ".C4::Context->zebraconfig('authorityserver')->{ccl2rpn});
811         system("cp -f $kohadir/etc/zebradb/ccl.properties $authorityserverdir/etc/ccl.properties");
812         print "Info: copied ccl.properties\n";
813         $created_dir_or_file++;
814     }
815     unless (-f "$authorityserverdir/etc/pqf.properties") {
816 #         system("cp -f $kohadir/etc/zebradb/pqf.properties ".C4::Context->zebraconfig('authorityserver')->{ccl2rpn});
817         system("cp -f $kohadir/etc/zebradb/pqf.properties $authorityserverdir/etc/pqf.properties");
818         print "Info: copied pqf.properties\n";
819         $created_dir_or_file++;
820     }
821     
822     #
823     # AUTHORITIES : copying mandatory files
824     #
825     unless (-f C4::Context->zebraconfig('authorityserver')->{config}) {
826     open ZD,">:utf8 ",C4::Context->zebraconfig('authorityserver')->{config};
827     print ZD "
828 # generated by KOHA/misc/migration_tools/rebuild_zebra.pl 
829 profilePath:\${srcdir:-.}:$authorityserverdir/tab/:$tabdir/tab/:\${srcdir:-.}/tab/
830
831 encoding: UTF-8
832 # Files that describe the attribute sets supported.
833 attset: auth1.att
834 attset: explain.att
835 attset: gils.att
836
837 modulePath:$modulesdir/modules/
838 # Specify record type
839 iso2709.recordType:grs.marcxml.record
840 recordType:grs.xml
841 recordId: (auth1,Local-Number)
842 storeKeys:1
843 storeData:1
844
845
846 # Lock File Area
847 lockDir: $authorityserverdir/lock
848 perm.anonymous:r
849 perm.kohaadmin:rw
850 register: $authorityserverdir/register:4G
851 shadow: $authorityserverdir/shadow:4G
852
853 # Temp File area for result sets
854 setTmpDir: $authorityserverdir/tmp
855
856 # Temp File area for index program
857 keyTmpDir: $authorityserverdir/key
858
859 # Approx. Memory usage during indexing
860 memMax: 40M
861 rank:rank-1
862     ";
863         print "Info: creating zebra-authorities.cfg\n";
864         $created_dir_or_file++;
865     }
866     
867     if ($created_dir_or_file) {
868         print "Info: created : $created_dir_or_file directories & files\n";
869     } else {
870         print "Info: file & directories OK\n";
871     }
872     
873 }
874 if ($biblios) {
875     if ( $verbose_logging ) {
876         print "====================\n";
877         print "checking directories & files for biblios\n";
878         print "====================\n";
879     }
880
881     #
882     # BIBLIOS : creating directory structure
883     #
884     unless (-d "$biblioserverdir") {
885         system("mkdir -p $biblioserverdir");
886         print "Info: created $biblioserverdir\n";
887         $created_dir_or_file++;
888     }
889     unless (-d "$biblioserverdir/lock") {
890         mkdir "$biblioserverdir/lock";
891         print "Info: created $biblioserverdir/lock\n";
892         $created_dir_or_file++;
893     }
894     unless (-d "$biblioserverdir/register") {
895         mkdir "$biblioserverdir/register";
896         print "Info: created $biblioserverdir/register\n";
897         $created_dir_or_file++;
898     }
899     unless (-d "$biblioserverdir/shadow") {
900         mkdir "$biblioserverdir/shadow";
901         print "Info: created $biblioserverdir/shadow\n";
902         $created_dir_or_file++;
903     }
904     unless (-d "$biblioserverdir/tab") {
905         mkdir "$biblioserverdir/tab";
906         print "Info: created $biblioserverdir/tab\n";
907         $created_dir_or_file++;
908     }
909     unless (-d "$biblioserverdir/key") {
910         mkdir "$biblioserverdir/key";
911         print "Info: created $biblioserverdir/key\n";
912         $created_dir_or_file++;
913     }
914     unless (-d "$biblioserverdir/etc") {
915         mkdir "$biblioserverdir/etc";
916         print "Info: created $biblioserverdir/etc\n";
917         $created_dir_or_file++;
918     }
919     
920     #
921     # BIBLIOS : copying mandatory files
922     #
923     # the record model, depending on marc flavour
924     unless (-f "$biblioserverdir/tab/record.abs") {
925         if (C4::Context->preference("marcflavour") eq "UNIMARC") {
926             system("cp -f $kohadir/etc/zebradb/marc_defs/unimarc/biblios/record.abs $biblioserverdir/tab/record.abs");
927             print "Info: copied record.abs for UNIMARC\n";
928         } else {
929             system("cp -f $kohadir/etc/zebradb/marc_defs/marc21/biblios/record.abs $biblioserverdir/tab/record.abs");
930             print "Info: copied record.abs for USMARC\n";
931         }
932         $created_dir_or_file++;
933     }
934     unless (-f "$biblioserverdir/tab/sort-string-utf.chr") {
935         system("cp -f $kohadir/etc/zebradb/lang_defs/fr/sort-string-utf.chr $biblioserverdir/tab/sort-string-utf.chr");
936         print "Info: copied sort-string-utf.chr\n";
937         $created_dir_or_file++;
938     }
939     unless (-f "$biblioserverdir/tab/word-phrase-utf.chr") {
940         system("cp -f $kohadir/etc/zebradb/lang_defs/fr/sort-string-utf.chr $biblioserverdir/tab/word-phrase-utf.chr");
941         print "Info: copied word-phase-utf.chr\n";
942         $created_dir_or_file++;
943     }
944     unless (-f "$biblioserverdir/tab/bib1.att") {
945         system("cp -f $kohadir/etc/zebradb/biblios/etc/bib1.att $biblioserverdir/tab/bib1.att");
946         print "Info: copied bib1.att\n";
947         $created_dir_or_file++;
948     }
949     unless (-f "$biblioserverdir/tab/default.idx") {
950         system("cp -f $kohadir/etc/zebradb/etc/default.idx $biblioserverdir/tab/default.idx");
951         print "Info: copied default.idx\n";
952         $created_dir_or_file++;
953     }
954     unless (-f "$biblioserverdir/etc/ccl.properties") {
955 #         system("cp -f $kohadir/etc/zebradb/ccl.properties ".C4::Context->zebraconfig('biblioserver')->{ccl2rpn});
956         system("cp -f $kohadir/etc/zebradb/ccl.properties $biblioserverdir/etc/ccl.properties");
957         print "Info: copied ccl.properties\n";
958         $created_dir_or_file++;
959     }
960     unless (-f "$biblioserverdir/etc/pqf.properties") {
961 #         system("cp -f $kohadir/etc/zebradb/pqf.properties ".C4::Context->zebraconfig('biblioserver')->{ccl2rpn});
962         system("cp -f $kohadir/etc/zebradb/pqf.properties $biblioserverdir/etc/pqf.properties");
963         print "Info: copied pqf.properties\n";
964         $created_dir_or_file++;
965     }
966     
967     #
968     # BIBLIOS : copying mandatory files
969     #
970     unless (-f C4::Context->zebraconfig('biblioserver')->{config}) {
971     open ZD,">:utf8 ",C4::Context->zebraconfig('biblioserver')->{config};
972     print ZD "
973 # generated by KOHA/misc/migrtion_tools/rebuild_zebra.pl 
974 profilePath:\${srcdir:-.}:$biblioserverdir/tab/:$tabdir/tab/:\${srcdir:-.}/tab/
975
976 encoding: UTF-8
977 # Files that describe the attribute sets supported.
978 attset:bib1.att
979 attset:explain.att
980 attset:gils.att
981
982 modulePath:$modulesdir/modules/
983 # Specify record type
984 iso2709.recordType:grs.marcxml.record
985 recordType:grs.xml
986 recordId: (bib1,Local-Number)
987 storeKeys:1
988 storeData:1
989
990
991 # Lock File Area
992 lockDir: $biblioserverdir/lock
993 perm.anonymous:r
994 perm.kohaadmin:rw
995 register: $biblioserverdir/register:4G
996 shadow: $biblioserverdir/shadow:4G
997
998 # Temp File area for result sets
999 setTmpDir: $biblioserverdir/tmp
1000
1001 # Temp File area for index program
1002 keyTmpDir: $biblioserverdir/key
1003
1004 # Approx. Memory usage during indexing
1005 memMax: 40M
1006 rank:rank-1
1007     ";
1008         print "Info: creating zebra-biblios.cfg\n";
1009         $created_dir_or_file++;
1010     }
1011     
1012     if ($created_dir_or_file) {
1013         print "Info: created : $created_dir_or_file directories & files\n";
1014     } else {
1015         print "Info: file & directories OK\n";
1016     }
1017     
1018 }
1019 }