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