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