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