/[webpac2]/trunk/run.pl
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/run.pl

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 389 by dpavlin, Sun Jan 22 13:38:17 2006 UTC revision 675 by dpavlin, Wed Sep 13 17:32:49 2006 UTC
# Line 4  use strict; Line 4  use strict;
4    
5  use Cwd qw/abs_path/;  use Cwd qw/abs_path/;
6  use File::Temp qw/tempdir/;  use File::Temp qw/tempdir/;
 use Data::Dumper;  
7  use lib './lib';  use lib './lib';
8    
9  use WebPAC::Common 0.02;  use WebPAC::Common 0.02;
10  use WebPAC::Lookup;  use WebPAC::Lookup 0.03;
11  use WebPAC::Input 0.03;  use WebPAC::Input 0.11;
12  use WebPAC::Store 0.03;  use WebPAC::Store 0.03;
13  use WebPAC::Normalize::XML;  use WebPAC::Normalize 0.11;
14  use WebPAC::Output::TT;  use WebPAC::Output::TT;
15  use WebPAC::Output::Estraier 0.08;  use WebPAC::Validate 0.06;
16    use WebPAC::Output::MARC;
17  use YAML qw/LoadFile/;  use YAML qw/LoadFile/;
18  use Getopt::Long;  use Getopt::Long;
19  use File::Path;  use File::Path;
20  use Time::HiRes qw/time/;  use Time::HiRes qw/time/;
21    use File::Slurp;
22    use Data::Dump qw/dump/;
23    use Storable qw/dclone/;
24    
25    use Proc::Queue size => 1;
26    use POSIX ":sys_wait_h"; # imports WNOHANG
27    
28  =head1 NAME  =head1 NAME
29    
# Line 41  limit loading to 100 records Line 47  limit loading to 100 records
47    
48  remove database and Hyper Estraier index before indexing  remove database and Hyper Estraier index before indexing
49    
50  =item --one=database_name  =item --only=database_name/input_filter
51    
52    reindex just single database (legacy name is --one)
53    
54  reindex just single database  C</input_filter> is optional part which can be C<name>
55    or C<type> from input
56    
57  =item --config conf/config.yml  =item --config conf/config.yml
58    
59  path to YAML configuration file  path to YAML configuration file
60    
61    =item --stats
62    
63    disable indexing, modify_* in configuration and dump statistics about field
64    and subfield usage for each input
65    
66    =item --validate path/to/validation_file
67    
68    turn on extra validation of imput records, see L<WebPAC::Validation>
69    
70    =item --marc-normalize conf/normalize/mapping.pl
71    
72    This option specifies normalisation file for MARC creation
73    
74    =item --marc-output out/marc/test.marc
75    
76    Optional path to output file
77    
78    =item --marc-lint
79    
80    By default turned on if C<--marc-normalize> is used. You can disable lint
81    messages with C<--no-marc-lint>.
82    
83    =item --marc-dump
84    
85    Force dump or input and marc record for debugging.
86    
87    =item --parallel 4
88    
89    Run databases in parallel (aproximatly same as number of processors in
90    machine if you want to use full load)
91    
92    =item --only-links
93    
94    Create just links
95    
96    =item --merge
97    
98    Create merged index of databases which have links
99    
100  =back  =back
101    
102  =cut  =cut
# Line 59  my $limit; Line 107  my $limit;
107  my $clean = 0;  my $clean = 0;
108  my $config = 'conf/config.yml';  my $config = 'conf/config.yml';
109  my $debug = 0;  my $debug = 0;
110  my $one_db_name;  my $only_filter;
111    my $stats = 0;
112    my $validate_path;
113    my ($marc_normalize, $marc_output);
114    my $marc_lint = 1;
115    my $marc_dump = 0;
116    my $parallel = 0;
117    my $only_links = 0;
118    my $merge = 0;
119    
120    my $log = _new WebPAC::Common()->_get_logger();
121    
122    my $hostname = `hostname`;
123    chomp($hostname);
124    $hostname =~ s/\..+$//;
125    if (-e "conf/$hostname.yml") {
126            $config = "conf/$hostname.yml";
127            $log->info("using host configuration file: $config");
128    }
129    
130  GetOptions(  GetOptions(
131          "limit=i" => \$limit,          "limit=i" => \$limit,
132          "offset=i" => \$offset,          "offset=i" => \$offset,
133          "clean" => \$clean,          "clean" => \$clean,
134          "one=s" => \$one_db_name,          "one=s" => \$only_filter,
135            "only=s" => \$only_filter,
136          "config" => \$config,          "config" => \$config,
137          "debug" => \$debug,          "debug+" => \$debug,
138            "stats" => \$stats,
139            "validate=s" => \$validate_path,
140            "marc-normalize=s" => \$marc_normalize,
141            "marc-output=s" => \$marc_output,
142            "marc-lint!" => \$marc_lint,
143            "marc-dump!" => \$marc_dump,
144            "parallel=i" => \$parallel,
145            "only-links!" => \$only_links,
146            "merge" => \$merge,
147  );  );
148    
149  $config = LoadFile($config);  $config = LoadFile($config);
150    
151  print "config = ",Dumper($config) if ($debug);  #print "config = ",dump($config) if ($debug);
152    
153  die "no databases in config file!\n" unless ($config->{databases});  die "no databases in config file!\n" unless ($config->{databases});
154    
155    $log->info( "-" x 79 );
156    
157    
158    my $estcmd_fh;
159    my $estcmd_path = './estcmd-merge.sh';
160    if ($merge) {
161            open($estcmd_fh, '>', $estcmd_path) || $log->logdie("can't open $estcmd_path: $!");
162            print $estcmd_fh 'cd /data/estraier/_node/ || exit 1',$/;
163            print $estcmd_fh 'sudo /etc/init.d/hyperestraier stop',$/;
164            $log->info("created merge batch file $estcmd_path");
165    }
166    
167    
168    my $validate;
169    $validate = new WebPAC::Validate(
170            path => $validate_path,
171    ) if ($validate_path);
172    
173    
174    my $use_indexer = $config->{use_indexer} || 'hyperestraier';
175    if ($stats) {
176            $log->debug("option --stats disables update of indexing engine...");
177            $use_indexer = undef;
178    } else {
179            $log->info("using $use_indexer indexing engine...");
180    }
181    
182    # disable indexing when creating marc
183    $use_indexer = undef if ($marc_normalize);
184    
185  my $total_rows = 0;  my $total_rows = 0;
186  my $start_t = time();  my $start_t = time();
187    
188    my @links;
189    
190    if ($parallel) {
191            $log->info("Using $parallel processes for speedup");
192            Proc::Queue::size($parallel);
193    }
194    
195  while (my ($database, $db_config) = each %{ $config->{databases} }) {  while (my ($database, $db_config) = each %{ $config->{databases} }) {
196    
197          next if ($one_db_name && $database !~ m/$one_db_name/i);          my ($only_database,$only_input) = split(m#/#, $only_filter) if ($only_filter);
198            next if ($only_database && $database !~ m/$only_database/i);
199    
200            if ($parallel) {
201                    my $f=fork;
202                    if(defined ($f) and $f==0) {
203                            $log->info("Created processes $$ for speedup");
204                    } else {
205                            next;
206                    }
207            }
208    
209            my $indexer;
210            if ($use_indexer) {
211    
212                    my $cfg_name = $use_indexer;
213                    $cfg_name =~ s/\-.*$//;
214    
215                    my $indexer_config = $config->{$cfg_name} || $log->logdie("can't find '$cfg_name' part in confguration");
216                    $indexer_config->{database} = $database;
217                    $indexer_config->{clean} = $clean;
218                    $indexer_config->{label} = $db_config->{name};
219    
220                    # force clean if database has links
221                    $indexer_config->{clean} = 1 if ($db_config->{links});
222    
223                    if ($use_indexer eq 'hyperestraier') {
224    
225                            # open Hyper Estraier database
226                            use WebPAC::Output::Estraier '0.10';
227                            $indexer = new WebPAC::Output::Estraier( %{ $indexer_config } );
228                    
229                    } elsif ($use_indexer eq 'hyperestraier-native') {
230    
231                            # open Hyper Estraier database
232                            use WebPAC::Output::EstraierNative;
233                            $indexer = new WebPAC::Output::EstraierNative( %{ $indexer_config } );
234    
235                    } elsif ($use_indexer eq 'kinosearch') {
236    
237                            # open KinoSearch
238                            use WebPAC::Output::KinoSearch;
239                            $indexer_config->{clean} = 1 unless (-e $indexer_config->{index_path});
240                            $indexer = new WebPAC::Output::KinoSearch( %{ $indexer_config } );
241    
242                    } else {
243                            $log->logdie("unknown use_indexer: $use_indexer");
244                    }
245    
246                    $log->logide("can't continue without valid indexer") unless ($indexer);
247            }
248    
         my $log = _new WebPAC::Common()->_get_logger();  
249    
250          #          #
251          # open Hyper Estraier database          # store Hyper Estraier links to other databases
252          #          #
253            if (ref($db_config->{links}) eq 'ARRAY' && $use_indexer) {
254                    foreach my $link (@{ $db_config->{links} }) {
255                            if ($use_indexer eq 'hyperestraier') {
256                                    if ($merge) {
257                                            print $estcmd_fh 'sudo -u www-data estcmd merge ' . $database . ' ' . $link->{to},$/;
258                                    } else {
259                                            $log->info("saving link $database -> $link->{to} [$link->{credit}]");
260                                            push @links, sub {
261                                                    $log->info("adding link $database -> $link->{to} [$link->{credit}]");
262                                                    $indexer->add_link(
263                                                            from => $database,
264                                                            to => $link->{to},
265                                                            credit => $link->{credit},
266                                                    );
267                                            };
268                                    }
269                            } else {
270                                    $log->warn("NOT IMPLEMENTED WITH $use_indexer: adding link $database -> $link->{to} [$link->{credit}]");
271                            }
272                    }
273            }
274            next if ($only_links);
275    
         my $est_config = $config->{hyperestraier} || $log->logdie("can't find 'hyperestraier' part in confguration");  
         $est_config->{database} = $database;  
         $est_config->{clean} = $clean;  
   
         my $est = new WebPAC::Output::Estraier( %{ $est_config } );  
276    
277          #          #
278          # now WebPAC::Store          # now WebPAC::Store
# Line 104  while (my ($database, $db_config) = each Line 283  while (my ($database, $db_config) = each
283          my $db_path = $config->{webpac}->{db_path} . '/' . $database;          my $db_path = $config->{webpac}->{db_path} . '/' . $database;
284    
285          if ($clean) {          if ($clean) {
286                  $log->info("creating new database $database in $db_path");                  $log->info("creating new database '$database' in $db_path");
287                  rmtree( $db_path ) || $log->warn("can't remove $db_path: $!");                  rmtree( $db_path ) || $log->warn("can't remove $db_path: $!");
288          } else {          } else {
289                  $log->info("working on $database in $db_path");                  $log->info("working on database '$database' in $db_path");
290          }          }
291    
292          my $db = new WebPAC::Store(          my $db = new WebPAC::Store(
# Line 134  while (my ($database, $db_config) = each Line 313  while (my ($database, $db_config) = each
313    
314          foreach my $input (@inputs) {          foreach my $input (@inputs) {
315    
316                    next if ($only_input && ($input->{name} !~ m#$only_input#i && $input->{type} !~ m#$only_input#i));
317    
318                  my $type = lc($input->{type});                  my $type = lc($input->{type});
319    
320                  die "I know only how to handle input types ", join(",", @supported_inputs), " not '$type'!\n" unless (grep(/$type/, @supported_inputs));                  die "I know only how to handle input types ", join(",", @supported_inputs), " not '$type'!\n" unless (grep(/$type/, @supported_inputs));
321    
322                  my $lookup = new WebPAC::Lookup(                  my $lookup;
323                          lookup_file => $input->{lookup},                  if ($input->{lookup}) {
324                  );                          $lookup = new WebPAC::Lookup(
325                                    lookup_file => $input->{lookup},
326                            );
327                            delete( $input->{lookup} );
328                    }
329    
330                  my $input_module = $config->{webpac}->{inputs}->{$type};                  my $input_module = $config->{webpac}->{inputs}->{$type};
331    
332                  $log->info("working on input $input->{path} [$input->{type}] using $input_module");                  $log->info("working on input '$input->{name}' in $input->{path} [type: $input->{type}] using $input_module",
333                            $input->{lookup} ? "lookup '$input->{lookup}'" : ""
334                    );
335    
336                    if ($stats) {
337                            # disable modification of records if --stats is in use
338                            delete($input->{modify_records});
339                            delete($input->{modify_file});
340                    }
341    
342                  my $input_db = new WebPAC::Input(                  my $input_db = new WebPAC::Input(
343                          module => $input_module,                          module => $input_module,
344                          code_page => $config->{webpac}->{webpac_encoding},                          encoding => $config->{webpac}->{webpac_encoding},
345                          limit => $limit || $input->{limit},                          limit => $limit || $input->{limit},
346                          offset => $offset,                          offset => $offset,
347                          lookup => $lookup,                          lookup_coderef => sub {
348                                    my $rec = shift || return;
349                                    $lookup->add( $rec );
350                            },
351                            recode => $input->{recode},
352                            stats => $stats,
353                            modify_records => $input->{modify_records},
354                            modify_file => $input->{modify_file},
355                  );                  );
356                  $log->logdie("can't create input using $input_module") unless ($input);                  $log->logdie("can't create input using $input_module") unless ($input);
357    
358                  my $maxmfn = $input_db->open(                  my $maxmfn = $input_db->open(
359                          path => $input->{path},                          path => $input->{path},
360                          code_page => $input->{encoding},        # database encoding                          code_page => $input->{encoding},        # database encoding
361                            %{ $input },
362                  );                  );
363    
364                  my $n = new WebPAC::Normalize::XML(                  my $report_fh;
365                  #       filter => { 'foo' => sub { shift } },                  if ($stats || $validate) {
366                          db => $db,                          my $path = "out/report/" . $database . '-' . $input->{name} . '.txt';
367                          lookup_regex => $lookup->regex,                          open($report_fh, '>', $path) || $log->logdie("can't open $path: $!");
368                          lookup => $lookup,  
369                          prefix => $input->{name},                          print $report_fh "Report for database '$database' input '$input->{name}' records ",
370                  );                                  $offset || 1, "-", $limit || $input->{limit} || $maxmfn, "\n\n";
371                            $log->info("Generating report file $path");
372                    }
373    
374                  my $normalize_path = $input->{normalize}->{path};                  my @norm_array = ref($input->{normalize}) eq 'ARRAY' ?
375                            @{ $input->{normalize} } : ( $input->{normalize} );
376    
377                  if ($normalize_path =~ m/\.xml$/i) {                  if ($marc_normalize) {
378                          $n->open(                          @norm_array = ( {
379                                  tag => $input->{normalize}->{tag},                                  path => $marc_normalize,
380                                  xml_file => $input->{normalize}->{path},                                  output => $marc_output || 'out/marc/' . $database . '-' . $input->{name} . '.marc',
381                          );                          } );
                 } elsif ($normalize_path =~ m/\.(?:yml|yaml)$/i) {  
                         $n->open_yaml(  
                                 path => $normalize_path,  
                                 tag => $input->{normalize}->{tag},  
                         );  
382                  }                  }
383    
384                  foreach my $pos ( 0 ... $input_db->size ) {                  foreach my $normalize (@norm_array) {
385    
386                            my $normalize_path = $normalize->{path} || $log->logdie("can't find normalize path in config");
387    
388                            $log->logdie("Found '$normalize_path' as normalization file which isn't supported any more!") unless ( $normalize_path =~ m!\.pl$!i );
389    
390                            my $rules = read_file( $normalize_path ) or die "can't open $normalize_path: $!";
391    
392                            $log->info("Using $normalize_path for normalization...");
393    
394                            my $marc = new WebPAC::Output::MARC(
395                                    path => $normalize->{output},
396                                    lint => $marc_lint,
397                                    dump => $marc_dump,
398                            ) if ($normalize->{output});
399    
400                            # reset position in database
401                            $input_db->seek(1);
402    
403                            # generate name of config key for indexer (strip everything after -)
404                            my $indexer_config = $use_indexer;
405                            $indexer_config =~ s/^(\w+)-?.*$/$1/g if ($indexer_config);
406    
407                            foreach my $pos ( 0 ... $input_db->size ) {
408    
409                                    my $row = $input_db->fetch || next;
410    
411                                    my $mfn = $row->{'000'}->[0];
412    
413                                    if (! $mfn || $mfn !~ m#^\d+$#) {
414                                            $log->warn("record $pos doesn't have valid MFN but '$mfn', using $pos");
415                                            $mfn = $pos;
416                                            push @{ $row->{'000'} }, $pos;
417                                    }
418    
419    
420                          my $row = $input_db->fetch || next;                                  if ($validate) {
421                                            if ( my $errors = $validate->validate_errors( $row, $input_db->dump ) ) {
422                                                    $log->error( "MFN $mfn validation error:\n",
423                                                            $validate->report_error( $errors )
424                                                    );
425                                            }
426                                    }
427    
428                          my $mfn = $row->{'000'}->[0];                                  my $ds_config = dclone($db_config);
429    
430                          if (! $mfn || $mfn !~ m#^\d+$#) {                                  # default values -> database key
431                                  $log->warn("record $pos doesn't have valid MFN but '$mfn', using $pos");                                  $ds_config->{_} = $database;
432                                  $mfn = $pos;  
433                                  push @{ $row->{'000'} }, $pos;                                  # current mfn
434                                    $ds_config->{_mfn} = $mfn;
435    
436                                    # attach current input
437                                    $ds_config->{input} = $input;
438    
439                                    my $ds = WebPAC::Normalize::data_structure(
440                                            row => $row,
441                                            rules => $rules,
442                                            lookup => $lookup ? $lookup->lookup_hash : undef,
443                                            config => $ds_config,
444                                            marc_encoding => 'utf-8',
445                                    );
446    
447                                    $db->save_ds(
448                                            id => $mfn,
449                                            ds => $ds,
450                                            prefix => $input->{name},
451                                    ) if ($ds && !$stats);
452    
453                                    $indexer->add(
454                                            id => $input->{name} . "/" . $mfn,
455                                            ds => $ds,
456                                            type => $config->{$indexer_config}->{type},
457                                    ) if ($indexer && $ds);
458    
459                                    if ($marc) {
460                                            my $i = 0;
461    
462                                            while (my $fields = WebPAC::Normalize::_get_marc_fields( fetch_next => 1 ) ) {
463                                                    $marc->add(
464                                                            id => $mfn . ( $i ? "/$i" : '' ),
465                                                            fields => $fields,
466                                                            leader => WebPAC::Normalize::marc_leader(),
467                                                            row => $row,
468                                                    );
469                                                    $i++;
470                                            }
471    
472                                            $log->info("Created $i instances of MFN $mfn\n") if ($i > 1);
473                                    }
474    
475                                    $total_rows++;
476                            }
477    
478                            if ($validate) {
479                                    my $errors = $validate->report;
480                                    if ($errors) {
481                                            $log->info("validation errors:\n$errors\n" );
482                                            print $report_fh "$errors\n" if ($report_fh);
483                                    }
484                          }                          }
485    
486                          my $ds = $n->data_structure($row);                          if ($stats) {
487                                    my $s = $input_db->stats;
488                                    $log->info("statistics of fields usage:\n$s");
489                                    print $report_fh "Statistics of fields usage:\n$s" if ($report_fh);
490                            }
491    
492                          $est->add(                          # close MARC file
493                                  id => $input->{name} . "/" . $mfn,                          $marc->finish if ($marc);
                                 ds => $ds,  
                                 type => $config->{hyperestraier}->{type},  
                         );  
494    
495                          $total_rows++;                          # close report
496                            close($report_fh) if ($report_fh)
497                  }                  }
498    
499          };          }
500    
501            eval { $indexer->finish } if ($indexer && $indexer->can('finish'));
502    
503          my $dt = time() - $start_t;          my $dt = time() - $start_t;
504          $log->info("$total_rows records indexed in " .          $log->info("$total_rows records ", $indexer ? "indexed " : "",
505                  sprintf("%.2f sec [%.2f rec/sec]",                  sprintf("in %.2f sec [%.2f rec/sec]",
506                          $dt, ($total_rows / $dt)                          $dt, ($total_rows / $dt)
507                  )                  )
508          );          );
509    
510          #  
511          # add Hyper Estraier links to other databases          # end forked process
512          #          if ($parallel) {
513          if (ref($db_config->{links}) eq 'ARRAY') {                  $log->info("parallel process $$ finished");
514                  foreach my $link (@{ $db_config->{links} }) {                  exit(0);
                         $log->info("adding link $database -> $link->{to} [$link->{credit}]");  
                         $est->add_link(  
                                 from => $database,  
                                 to => $link->{to},  
                                 credit => $link->{credit},  
                         );  
                 }  
515          }          }
516    
517  }  }
518    
519    if ($parallel) {
520            # wait all children to finish
521            sleep(1) while wait != -1;
522            $log->info("all parallel processes finished");
523    }
524    
525    #
526    # handle links or merge after indexing
527    #
528    
529    if ($merge) {
530            print $estcmd_fh 'sudo /etc/init.d/hyperestraier start',$/;
531            close($estcmd_fh);
532            chmod 0700, $estcmd_path || $log->warn("can't chmod 0700 $estcmd_path: $!");
533            system $estcmd_path;
534    } else {
535            foreach my $link (@links) {
536                    $log->logdie("coderef in link ", Dumper($link), " is ", ref($link), " and not CODE") unless (ref($link) eq 'CODE');
537                    $link->();
538            }
539    }

Legend:
Removed from v.389  
changed lines
  Added in v.675

  ViewVC Help
Powered by ViewVC 1.1.26