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

Legend:
Removed from v.511  
changed lines
  Added in v.684

  ViewVC Help
Powered by ViewVC 1.1.26