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