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