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