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

Legend:
Removed from v.512  
changed lines
  Added in v.702

  ViewVC Help
Powered by ViewVC 1.1.26