Bug 5579: remove items from MARC bib
[srvgit] / 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' );
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 $num_records_deleted = 0;
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             $num_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);
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 $num_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                 #CALL  sub ProcessItems
324                 my @items=GetItemsInfo($record_number,'intra',30);
325                 if (@items){
326                     my $record=MARC::Record->new;
327                     my @itemsrecord;
328                     foreach my $item (@items){
329                         my $record=Item2Marc($item, $record_number);                        
330                         push @itemsrecord, $record->field($itemtag);
331                         #if xml then print itemfield as xml
332                         # and update marcxml
333                         # else push field
334                     }
335                     $record->insert_fields_ordered(@itemsrecord);
336                     my $itemsxml=$record->as_xml_record();
337                     my $searchstring='<record>\n';
338                     my $index=index($itemsxml,'<record>\n',0);
339                     $itemsxml=substr($itemsxml,$index+length($searchstring));
340                     $searchstring='</record>';
341                     $marcxml=substr($marcxml,0,index($marcxml,$searchstring));
342                     $marcxml.=$itemsxml;
343                 }
344             }
345             if ( $marcxml ) {
346                 print OUT $marcxml if $marcxml;
347                 $num_exported++;
348             }
349             next;
350         }
351         my ($marc) = get_corrected_marc_record($record_type, $record_number, $noxml);
352         if (defined $marc) {
353             # FIXME - when more than one record is exported and $as_xml is true,
354             # the output file is not valid XML - it's just multiple <record> elements
355             # strung together with no single root element.  zebraidx doesn't seem
356             # to care, though, at least if you're using the GRS-1 filter.  It does
357             # care if you're using the DOM filter, which requires valid XML file(s).
358             print OUT ($as_xml) ? $marc->as_xml_record(C4::Context->preference('marcflavour')) : $marc->as_usmarc();
359             $num_exported++;
360         }
361     }
362     print "\nRecords exported: $num_exported\n" if ( $verbose_logging );
363     close OUT;
364     return $num_exported;
365 }
366
367 sub export_marc_records_from_list {
368     my ($record_type, $entries, $directory, $as_xml, $noxml) = @_;
369
370     my $num_exported = 0;
371     open (OUT, ">:utf8 ", "$directory/exported_records") or die $!;
372     my $i = 0;
373     my %found = ();
374     foreach my $record_number ( map { $_->{biblio_auth_number} }
375                                 grep { !$found{ $_->{biblio_auth_number} }++ }
376                                 @$entries ) {
377         print "." if ( $verbose_logging );
378         print "\r$i" unless ($i++ %100 or !$verbose_logging);
379         my ($marc) = get_corrected_marc_record($record_type, $record_number, $noxml);
380         if (defined $marc) {
381             # FIXME - when more than one record is exported and $as_xml is true,
382             # the output file is not valid XML - it's just multiple <record> elements
383             # strung together with no single root element.  zebraidx doesn't seem
384             # to care, though, at least if you're using the GRS-1 filter.  It does
385             # care if you're using the DOM filter, which requires valid XML file(s).
386             print OUT ($as_xml) ? $marc->as_xml_record(C4::Context->preference('marcflavour')) : $marc->as_usmarc();
387             $num_exported++;
388         }
389     }
390     print "\nRecords exported: $num_exported\n" if ( $verbose_logging );
391     close OUT;
392     return $num_exported;
393 }
394
395 sub generate_deleted_marc_records {
396     my ($record_type, $entries, $directory, $as_xml) = @_;
397
398     my $num_exported = 0;
399     open (OUT, ">:utf8 ", "$directory/exported_records") or die $!;
400     my $i = 0;
401     foreach my $record_number (map { $_->{biblio_auth_number} } @$entries ) {
402         print "\r$i" unless ($i++ %100 or !$verbose_logging);
403         print "." if ( $verbose_logging );
404
405         my $marc = MARC::Record->new();
406         if ($record_type eq 'biblio') {
407             fix_biblio_ids($marc, $record_number, $record_number);
408         } else {
409             fix_authority_id($marc, $record_number);
410         }
411         if (C4::Context->preference("marcflavour") eq "UNIMARC") {
412             fix_unimarc_100($marc);
413         }
414
415         print OUT ($as_xml) ? $marc->as_xml_record(C4::Context->preference("marcflavour")) : $marc->as_usmarc();
416         $num_exported++;
417     }
418     print "\nRecords exported: $num_exported\n" if ( $verbose_logging );
419     close OUT;
420     return $num_exported;
421     
422
423 }
424
425 sub get_corrected_marc_record {
426     my ($record_type, $record_number, $noxml) = @_;
427
428     my $marc = get_raw_marc_record($record_type, $record_number, $noxml); 
429
430     if (defined $marc) {
431         fix_leader($marc);
432         if ($record_type eq 'biblio') {
433             my $succeeded = fix_biblio_ids($marc, $record_number);
434             return unless $succeeded;
435         } else {
436             fix_authority_id($marc, $record_number);
437         }
438         if (C4::Context->preference("marcflavour") eq "UNIMARC") {
439             fix_unimarc_100($marc);
440         }
441     }
442
443     return $marc;
444 }
445
446 sub get_raw_marc_record {
447     my ($record_type, $record_number, $noxml) = @_;
448   
449     my $marc; 
450     if ($record_type eq 'biblio') {
451         if ($noxml) {
452             my $fetch_sth = $dbh->prepare_cached("SELECT marc FROM biblioitems WHERE biblionumber = ?");
453             $fetch_sth->execute($record_number);
454             if (my ($blob) = $fetch_sth->fetchrow_array) {
455                 $marc = MARC::Record->new_from_usmarc($blob);
456                 $fetch_sth->finish();
457             } else {
458                 return; # failure to find a bib is not a problem -
459                         # a delete could have been done before
460                         # trying to process a record update
461             }
462         } else {
463             eval { $marc = GetMarcBiblio($record_number); };
464             if ($@) {
465                 # here we do warn since catching an exception
466                 # means that the bib was found but failed
467                 # to be parsed
468                 warn "error retrieving biblio $record_number";
469                 return;
470             }
471         }
472     } else {
473         eval { $marc = GetAuthority($record_number); };
474         if ($@) {
475             warn "error retrieving authority $record_number";
476             return;
477         }
478     }
479     return $marc;
480 }
481
482 sub fix_leader {
483     # FIXME - this routine is suspect
484     # It blanks the Leader/00-05 and Leader/12-16 to
485     # force them to be recalculated correct when
486     # the $marc->as_usmarc() or $marc->as_xml() is called.
487     # But why is this necessary?  It would be a serious bug
488     # in MARC::Record (definitely) and MARC::File::XML (arguably) 
489     # if they are emitting incorrect leader values.
490     my $marc = shift;
491
492     my $leader = $marc->leader;
493     substr($leader,  0, 5) = '     ';
494     substr($leader, 10, 7) = '22     ';
495     $marc->leader(substr($leader, 0, 24));
496 }
497
498 sub fix_biblio_ids {
499     # FIXME - it is essential to ensure that the biblionumber is present,
500     #         otherwise, Zebra will choke on the record.  However, this
501     #         logic belongs in the relevant C4::Biblio APIs.
502     my $marc = shift;
503     my $biblionumber = shift;
504     my $biblioitemnumber;
505     if (@_) {
506         $biblioitemnumber = shift;
507     } else {    
508         my $sth = $dbh->prepare(
509             "SELECT biblioitemnumber FROM biblioitems WHERE biblionumber=?");
510         $sth->execute($biblionumber);
511         ($biblioitemnumber) = $sth->fetchrow_array;
512         $sth->finish;
513         unless ($biblioitemnumber) {
514             warn "failed to get biblioitemnumber for biblio $biblionumber";
515             return 0;
516         }
517     }
518
519     # FIXME - this is cheating on two levels
520     # 1. C4::Biblio::_koha_marc_update_bib_ids is meant to be an internal function
521     # 2. Making sure that the biblionumber and biblioitemnumber are correct and
522     #    present in the MARC::Record object ought to be part of GetMarcBiblio.
523     #
524     # On the other hand, this better for now than what rebuild_zebra.pl used to
525     # do, which was duplicate the code for inserting the biblionumber 
526     # and biblioitemnumber
527     C4::Biblio::_koha_marc_update_bib_ids($marc, '', $biblionumber, $biblioitemnumber);
528
529     return 1;
530 }
531
532 sub fix_authority_id {
533     # FIXME - as with fix_biblio_ids, the authid must be present
534     #         for Zebra's sake.  However, this really belongs
535     #         in C4::AuthoritiesMarc.
536     my ($marc, $authid) = @_;
537     unless ($marc->field('001') and $marc->field('001')->data() eq $authid){
538         $marc->delete_field($marc->field('001'));
539         $marc->insert_fields_ordered(MARC::Field->new('001',$authid));
540     }
541 }
542
543 sub fix_unimarc_100 {
544     # FIXME - again, if this is necessary, it belongs in C4::AuthoritiesMarc.
545     my $marc = shift;
546
547     my $string;
548     if ( length($marc->subfield( 100, "a" )) == 35 ) {
549         $string = $marc->subfield( 100, "a" );
550         my $f100 = $marc->field(100);
551         $marc->delete_field($f100);
552     }
553     else {
554         $string = POSIX::strftime( "%Y%m%d", localtime );
555         $string =~ s/\-//g;
556         $string = sprintf( "%-*s", 35, $string );
557     }
558     substr( $string, 22, 6, "frey50" );
559     unless ( length($marc->subfield( 100, "a" )) == 35 ) {
560         $marc->delete_field($marc->field(100));
561         $marc->insert_grouped_field(MARC::Field->new( 100, "", "", "a" => $string ));
562     }
563 }
564
565 sub do_indexing {
566     my ($record_type, $op, $record_dir, $reset_index, $noshadow, $record_format, $zebraidx_log_opt) = @_;
567
568     my $zebra_server  = ($record_type eq 'biblio') ? 'biblioserver' : 'authorityserver';
569     my $zebra_db_name = ($record_type eq 'biblio') ? 'biblios' : 'authorities';
570     my $zebra_config  = C4::Context->zebraconfig($zebra_server)->{'config'};
571     my $zebra_db_dir  = C4::Context->zebraconfig($zebra_server)->{'directory'};
572
573     system("zebraidx -c $zebra_config $zebraidx_log_opt -g $record_format -d $zebra_db_name init") if $reset_index;
574     system("zebraidx -c $zebra_config $zebraidx_log_opt $noshadow -g $record_format -d $zebra_db_name $op $record_dir");
575     system("zebraidx -c $zebra_config $zebraidx_log_opt -g $record_format -d $zebra_db_name commit") unless $noshadow;
576
577 }
578
579 sub print_usage {
580     print <<_USAGE_;
581 $0: reindex MARC bibs and/or authorities in Zebra.
582
583 Use this batch job to reindex all biblio or authority
584 records in your Koha database.  This job is useful
585 only if you are using Zebra; if you are using the 'NoZebra'
586 mode, this job should not be used.
587
588 Parameters:
589     -b                      index bibliographic records
590
591     -a                      index authority records
592
593     -z                      select only updated and deleted
594                             records marked in the zebraqueue
595                             table.  Cannot be used with -r
596                             or -s.
597
598     -r                      clear Zebra index before
599                             adding records to index
600
601     -d                      Temporary directory for indexing.
602                             If not specified, one is automatically
603                             created.  The export directory
604                             is automatically deleted unless
605                             you supply the -k switch.
606
607     -k                      Do not delete export directory.
608
609     -s                      Skip export.  Used if you have
610                             already exported the records 
611                             in a previous run.
612
613     -noxml                  index from ISO MARC blob
614                             instead of MARC XML.  This
615                             option is recommended only
616                             for advanced user.
617
618     -x                      export and index as xml instead of is02709 (biblios only).
619                             use this if you might have records > 99,999 chars,
620                                                         
621     -nosanitize             export biblio/authority records directly from DB marcxml
622                             field without sanitizing records. It speed up
623                             dump process but could fail if DB contains badly
624                             encoded records. Works only with -x,
625
626     -w                      skip shadow indexing for this batch
627
628     -y                      do NOT clear zebraqueue after indexing; normally,
629                             after doing batch indexing, zebraqueue should be
630                             marked done for the affected record type(s) so that
631                             a running zebraqueue_daemon doesn't try to reindex
632                             the same records - specify -y to override this.  
633                             Cannot be used with -z.
634
635     -v                      increase the amount of logging.  Normally only 
636                             warnings and errors from the indexing are shown.
637
638     -munge-config           Deprecated option to try
639                             to fix Zebra config files.
640     --help or -h            show this message.
641 _USAGE_
642 }
643
644 # FIXME: the following routines are deprecated and 
645 # will be removed once it is determined whether
646 # a script to fix Zebra configuration files is 
647 # actually needed.
648 sub munge_config {
649 #
650 # creating zebra-biblios.cfg depending on system
651 #
652
653 # getting zebraidx directory
654 my $zebraidxdir;
655 foreach (qw(/usr/local/bin/zebraidx
656         /opt/bin/zebraidx
657         /usr/bin/zebraidx
658         )) {
659     if ( -f $_ ) {
660         $zebraidxdir=$_;
661     }
662 }
663
664 unless ($zebraidxdir) {
665     print qq|
666     ERROR: could not find zebraidx directory
667     ERROR: Either zebra is not installed,
668     ERROR: or it's in a directory I don't checked.
669     ERROR: do a which zebraidx and edit this file to add the result you get
670 |;
671     exit;
672 }
673 $zebraidxdir =~ s/\/bin\/.*//;
674 print "Info : zebra is in $zebraidxdir \n";
675
676 # getting modules directory
677 my $modulesdir;
678 foreach (qw(/usr/local/lib/idzebra-2.0/modules/mod-grs-xml.so
679             /usr/local/lib/idzebra/modules/mod-grs-xml.so
680             /usr/lib/idzebra/modules/mod-grs-xml.so
681             /usr/lib/idzebra-2.0/modules/mod-grs-xml.so
682         )) {
683     if ( -f $_ ) {
684         $modulesdir=$_;
685     }
686 }
687
688 unless ($modulesdir) {
689     print qq|
690     ERROR: could not find mod-grs-xml.so directory
691     ERROR: Either zebra is not properly compiled (libxml2 is not setup and you don t have mod-grs-xml.so,
692     ERROR: or it's in a directory I don't checked.
693     ERROR: find where mod-grs-xml.so is and edit this file to add the result you get
694 |;
695     exit;
696 }
697 $modulesdir =~ s/\/modules\/.*//;
698 print "Info: zebra modules dir : $modulesdir\n";
699
700 # getting tab directory
701 my $tabdir;
702 foreach (qw(/usr/local/share/idzebra/tab/explain.att
703             /usr/local/share/idzebra-2.0/tab/explain.att
704             /usr/share/idzebra/tab/explain.att
705             /usr/share/idzebra-2.0/tab/explain.att
706         )) {
707     if ( -f $_ ) {
708         $tabdir=$_;
709     }
710 }
711
712 unless ($tabdir) {
713     print qq|
714     ERROR: could not find explain.att directory
715     ERROR: Either zebra is not properly compiled,
716     ERROR: or it's in a directory I don't checked.
717     ERROR: find where explain.att is and edit this file to add the result you get
718 |;
719     exit;
720 }
721 $tabdir =~ s/\/tab\/.*//;
722 print "Info: tab dir : $tabdir\n";
723
724 #
725 # AUTHORITIES creating directory structure
726 #
727 my $created_dir_or_file = 0;
728 if ($authorities) {
729     if ( $verbose_logging ) {
730         print "====================\n";
731         print "checking directories & files for authorities\n";
732         print "====================\n";
733     }
734     unless (-d "$authorityserverdir") {
735         system("mkdir -p $authorityserverdir");
736         print "Info: created $authorityserverdir\n";
737         $created_dir_or_file++;
738     }
739     unless (-d "$authorityserverdir/lock") {
740         mkdir "$authorityserverdir/lock";
741         print "Info: created $authorityserverdir/lock\n";
742         $created_dir_or_file++;
743     }
744     unless (-d "$authorityserverdir/register") {
745         mkdir "$authorityserverdir/register";
746         print "Info: created $authorityserverdir/register\n";
747         $created_dir_or_file++;
748     }
749     unless (-d "$authorityserverdir/shadow") {
750         mkdir "$authorityserverdir/shadow";
751         print "Info: created $authorityserverdir/shadow\n";
752         $created_dir_or_file++;
753     }
754     unless (-d "$authorityserverdir/tab") {
755         mkdir "$authorityserverdir/tab";
756         print "Info: created $authorityserverdir/tab\n";
757         $created_dir_or_file++;
758     }
759     unless (-d "$authorityserverdir/key") {
760         mkdir "$authorityserverdir/key";
761         print "Info: created $authorityserverdir/key\n";
762         $created_dir_or_file++;
763     }
764     
765     unless (-d "$authorityserverdir/etc") {
766         mkdir "$authorityserverdir/etc";
767         print "Info: created $authorityserverdir/etc\n";
768         $created_dir_or_file++;
769     }
770     
771     #
772     # AUTHORITIES : copying mandatory files
773     #
774     # the record model, depending on marc flavour
775     unless (-f "$authorityserverdir/tab/record.abs") {
776         if (C4::Context->preference("marcflavour") eq "UNIMARC") {
777             system("cp -f $kohadir/etc/zebradb/marc_defs/unimarc/authorities/record.abs $authorityserverdir/tab/record.abs");
778             print "Info: copied record.abs for UNIMARC\n";
779         } else {
780             system("cp -f $kohadir/etc/zebradb/marc_defs/marc21/authorities/record.abs $authorityserverdir/tab/record.abs");
781             print "Info: copied record.abs for USMARC\n";
782         }
783         $created_dir_or_file++;
784     }
785     unless (-f "$authorityserverdir/tab/sort-string-utf.chr") {
786         system("cp -f $kohadir/etc/zebradb/lang_defs/fr/sort-string-utf.chr $authorityserverdir/tab/sort-string-utf.chr");
787         print "Info: copied sort-string-utf.chr\n";
788         $created_dir_or_file++;
789     }
790     unless (-f "$authorityserverdir/tab/word-phrase-utf.chr") {
791         system("cp -f $kohadir/etc/zebradb/lang_defs/fr/sort-string-utf.chr $authorityserverdir/tab/word-phrase-utf.chr");
792         print "Info: copied word-phase-utf.chr\n";
793         $created_dir_or_file++;
794     }
795     unless (-f "$authorityserverdir/tab/auth1.att") {
796         system("cp -f $kohadir/etc/zebradb/authorities/etc/bib1.att $authorityserverdir/tab/auth1.att");
797         print "Info: copied auth1.att\n";
798         $created_dir_or_file++;
799     }
800     unless (-f "$authorityserverdir/tab/default.idx") {
801         system("cp -f $kohadir/etc/zebradb/etc/default.idx $authorityserverdir/tab/default.idx");
802         print "Info: copied default.idx\n";
803         $created_dir_or_file++;
804     }
805     
806     unless (-f "$authorityserverdir/etc/ccl.properties") {
807 #         system("cp -f $kohadir/etc/zebradb/ccl.properties ".C4::Context->zebraconfig('authorityserver')->{ccl2rpn});
808         system("cp -f $kohadir/etc/zebradb/ccl.properties $authorityserverdir/etc/ccl.properties");
809         print "Info: copied ccl.properties\n";
810         $created_dir_or_file++;
811     }
812     unless (-f "$authorityserverdir/etc/pqf.properties") {
813 #         system("cp -f $kohadir/etc/zebradb/pqf.properties ".C4::Context->zebraconfig('authorityserver')->{ccl2rpn});
814         system("cp -f $kohadir/etc/zebradb/pqf.properties $authorityserverdir/etc/pqf.properties");
815         print "Info: copied pqf.properties\n";
816         $created_dir_or_file++;
817     }
818     
819     #
820     # AUTHORITIES : copying mandatory files
821     #
822     unless (-f C4::Context->zebraconfig('authorityserver')->{config}) {
823     open ZD,">:utf8 ",C4::Context->zebraconfig('authorityserver')->{config};
824     print ZD "
825 # generated by KOHA/misc/migration_tools/rebuild_zebra.pl 
826 profilePath:\${srcdir:-.}:$authorityserverdir/tab/:$tabdir/tab/:\${srcdir:-.}/tab/
827
828 encoding: UTF-8
829 # Files that describe the attribute sets supported.
830 attset: auth1.att
831 attset: explain.att
832 attset: gils.att
833
834 modulePath:$modulesdir/modules/
835 # Specify record type
836 iso2709.recordType:grs.marcxml.record
837 recordType:grs.xml
838 recordId: (auth1,Local-Number)
839 storeKeys:1
840 storeData:1
841
842
843 # Lock File Area
844 lockDir: $authorityserverdir/lock
845 perm.anonymous:r
846 perm.kohaadmin:rw
847 register: $authorityserverdir/register:4G
848 shadow: $authorityserverdir/shadow:4G
849
850 # Temp File area for result sets
851 setTmpDir: $authorityserverdir/tmp
852
853 # Temp File area for index program
854 keyTmpDir: $authorityserverdir/key
855
856 # Approx. Memory usage during indexing
857 memMax: 40M
858 rank:rank-1
859     ";
860         print "Info: creating zebra-authorities.cfg\n";
861         $created_dir_or_file++;
862     }
863     
864     if ($created_dir_or_file) {
865         print "Info: created : $created_dir_or_file directories & files\n";
866     } else {
867         print "Info: file & directories OK\n";
868     }
869     
870 }
871 if ($biblios) {
872     if ( $verbose_logging ) {
873         print "====================\n";
874         print "checking directories & files for biblios\n";
875         print "====================\n";
876     }
877
878     #
879     # BIBLIOS : creating directory structure
880     #
881     unless (-d "$biblioserverdir") {
882         system("mkdir -p $biblioserverdir");
883         print "Info: created $biblioserverdir\n";
884         $created_dir_or_file++;
885     }
886     unless (-d "$biblioserverdir/lock") {
887         mkdir "$biblioserverdir/lock";
888         print "Info: created $biblioserverdir/lock\n";
889         $created_dir_or_file++;
890     }
891     unless (-d "$biblioserverdir/register") {
892         mkdir "$biblioserverdir/register";
893         print "Info: created $biblioserverdir/register\n";
894         $created_dir_or_file++;
895     }
896     unless (-d "$biblioserverdir/shadow") {
897         mkdir "$biblioserverdir/shadow";
898         print "Info: created $biblioserverdir/shadow\n";
899         $created_dir_or_file++;
900     }
901     unless (-d "$biblioserverdir/tab") {
902         mkdir "$biblioserverdir/tab";
903         print "Info: created $biblioserverdir/tab\n";
904         $created_dir_or_file++;
905     }
906     unless (-d "$biblioserverdir/key") {
907         mkdir "$biblioserverdir/key";
908         print "Info: created $biblioserverdir/key\n";
909         $created_dir_or_file++;
910     }
911     unless (-d "$biblioserverdir/etc") {
912         mkdir "$biblioserverdir/etc";
913         print "Info: created $biblioserverdir/etc\n";
914         $created_dir_or_file++;
915     }
916     
917     #
918     # BIBLIOS : copying mandatory files
919     #
920     # the record model, depending on marc flavour
921     unless (-f "$biblioserverdir/tab/record.abs") {
922         if (C4::Context->preference("marcflavour") eq "UNIMARC") {
923             system("cp -f $kohadir/etc/zebradb/marc_defs/unimarc/biblios/record.abs $biblioserverdir/tab/record.abs");
924             print "Info: copied record.abs for UNIMARC\n";
925         } else {
926             system("cp -f $kohadir/etc/zebradb/marc_defs/marc21/biblios/record.abs $biblioserverdir/tab/record.abs");
927             print "Info: copied record.abs for USMARC\n";
928         }
929         $created_dir_or_file++;
930     }
931     unless (-f "$biblioserverdir/tab/sort-string-utf.chr") {
932         system("cp -f $kohadir/etc/zebradb/lang_defs/fr/sort-string-utf.chr $biblioserverdir/tab/sort-string-utf.chr");
933         print "Info: copied sort-string-utf.chr\n";
934         $created_dir_or_file++;
935     }
936     unless (-f "$biblioserverdir/tab/word-phrase-utf.chr") {
937         system("cp -f $kohadir/etc/zebradb/lang_defs/fr/sort-string-utf.chr $biblioserverdir/tab/word-phrase-utf.chr");
938         print "Info: copied word-phase-utf.chr\n";
939         $created_dir_or_file++;
940     }
941     unless (-f "$biblioserverdir/tab/bib1.att") {
942         system("cp -f $kohadir/etc/zebradb/biblios/etc/bib1.att $biblioserverdir/tab/bib1.att");
943         print "Info: copied bib1.att\n";
944         $created_dir_or_file++;
945     }
946     unless (-f "$biblioserverdir/tab/default.idx") {
947         system("cp -f $kohadir/etc/zebradb/etc/default.idx $biblioserverdir/tab/default.idx");
948         print "Info: copied default.idx\n";
949         $created_dir_or_file++;
950     }
951     unless (-f "$biblioserverdir/etc/ccl.properties") {
952 #         system("cp -f $kohadir/etc/zebradb/ccl.properties ".C4::Context->zebraconfig('biblioserver')->{ccl2rpn});
953         system("cp -f $kohadir/etc/zebradb/ccl.properties $biblioserverdir/etc/ccl.properties");
954         print "Info: copied ccl.properties\n";
955         $created_dir_or_file++;
956     }
957     unless (-f "$biblioserverdir/etc/pqf.properties") {
958 #         system("cp -f $kohadir/etc/zebradb/pqf.properties ".C4::Context->zebraconfig('biblioserver')->{ccl2rpn});
959         system("cp -f $kohadir/etc/zebradb/pqf.properties $biblioserverdir/etc/pqf.properties");
960         print "Info: copied pqf.properties\n";
961         $created_dir_or_file++;
962     }
963     
964     #
965     # BIBLIOS : copying mandatory files
966     #
967     unless (-f C4::Context->zebraconfig('biblioserver')->{config}) {
968     open ZD,">:utf8 ",C4::Context->zebraconfig('biblioserver')->{config};
969     print ZD "
970 # generated by KOHA/misc/migrtion_tools/rebuild_zebra.pl 
971 profilePath:\${srcdir:-.}:$biblioserverdir/tab/:$tabdir/tab/:\${srcdir:-.}/tab/
972
973 encoding: UTF-8
974 # Files that describe the attribute sets supported.
975 attset:bib1.att
976 attset:explain.att
977 attset:gils.att
978
979 modulePath:$modulesdir/modules/
980 # Specify record type
981 iso2709.recordType:grs.marcxml.record
982 recordType:grs.xml
983 recordId: (bib1,Local-Number)
984 storeKeys:1
985 storeData:1
986
987
988 # Lock File Area
989 lockDir: $biblioserverdir/lock
990 perm.anonymous:r
991 perm.kohaadmin:rw
992 register: $biblioserverdir/register:4G
993 shadow: $biblioserverdir/shadow:4G
994
995 # Temp File area for result sets
996 setTmpDir: $biblioserverdir/tmp
997
998 # Temp File area for index program
999 keyTmpDir: $biblioserverdir/key
1000
1001 # Approx. Memory usage during indexing
1002 memMax: 40M
1003 rank:rank-1
1004     ";
1005         print "Info: creating zebra-biblios.cfg\n";
1006         $created_dir_or_file++;
1007     }
1008     
1009     if ($created_dir_or_file) {
1010         print "Info: created : $created_dir_or_file directories & files\n";
1011     } else {
1012         print "Info: file & directories OK\n";
1013     }
1014     
1015 }
1016 }