/[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 423 by dpavlin, Wed Mar 22 00:18:56 2006 UTC revision 699 by dpavlin, Mon Sep 25 12:51: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;
15  use WebPAC::Output::TT;  use WebPAC::Output::TT;
16  use WebPAC::Output::Estraier '0.10';  use WebPAC::Validate 0.06;
17  use YAML qw/LoadFile/;  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;
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 41  limit loading to 100 records Line 48  limit loading to 100 records
48    
49  remove database and Hyper Estraier index before indexing  remove database and Hyper Estraier index before indexing
50    
51  =item --only=database_name  =item --only=database_name/input_filter
52    
53  reindex just single database (legacy name is --one)  reindex just single database (legacy name is --one)
54    
55    C</input_filter> is optional part which can be C<name>
56    or C<type> from input
57    
58  =item --config conf/config.yml  =item --config conf/config.yml
59    
60  path to YAML configuration file  path to YAML configuration file
61    
62    =item --stats
63    
64    disable indexing, modify_* in configuration and dump statistics about field
65    and subfield usage for each input
66    
67    =item --validate path/to/validation_file
68    
69    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    =item --only-links
94    
95    Create just links
96    
97    =item --merge
98    
99    Create merged index of databases which have links
100    
101  =back  =back
102    
103  =cut  =cut
# Line 57  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_db_name;  my $only_filter;
112    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,
125          "offset=i" => \$offset,          "offset=i" => \$offset,
126          "clean" => \$clean,          "clean" => \$clean,
127          "one=s" => \$only_db_name,          "one=s" => \$only_filter,
128          "only=s" => \$only_db_name,          "only=s" => \$only_filter,
129          "config" => \$config,          "config" => \$config_path,
130          "debug" => \$debug,          "debug+" => \$debug,
131            "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 = ",dump($config) if ($debug);
145    
146    die "no databases in config file!\n" unless ($config->databases);
147    
148    $log->info( "-" x 79 );
149    
150    
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) {
169            $log->debug("option --stats disables update of indexing engine...");
170            $use_indexer = undef;
171    } else {
172            $log->info("using $use_indexer indexing engine...");
173    }
174    
175    # disable indexing when creating marc
176    $use_indexer = undef if ($marc_normalize);
177    
178  print "config = ",Dumper($config) if ($debug);  # parse normalize files and create source files for lookup and normalization
179    
180  die "no databases in config file!\n" unless ($config->{databases});  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);
195            next if ($only_database && $database !~ m/$only_database/i);
196    
197            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) {
208    
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;
214                    $indexer_config->{clean} = $clean;
215                    $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') {
221    
222                            # open Hyper Estraier database
223                            use WebPAC::Output::Estraier '0.10';
224                            $indexer = new WebPAC::Output::Estraier( %{ $indexer_config } );
225                    
226                    } elsif ($use_indexer eq 'hyperestraier-native') {
227    
228          next if ($only_db_name && $database !~ m/$only_db_name/i);                          # open Hyper Estraier database
229                            use WebPAC::Output::EstraierNative;
230                            $indexer = new WebPAC::Output::EstraierNative( %{ $indexer_config } );
231    
232                    } elsif ($use_indexer eq 'kinosearch') {
233    
234                            # open KinoSearch
235                            use WebPAC::Output::KinoSearch;
236                            $indexer_config->{clean} = 1 unless (-e $indexer_config->{index_path});
237                            $indexer = new WebPAC::Output::KinoSearch( %{ $indexer_config } );
238    
239                    } else {
240                            $log->logdie("unknown use_indexer: $use_indexer");
241                    }
242    
243                    $log->logide("can't continue without valid indexer") unless ($indexer);
244            }
245    
         my $log = _new WebPAC::Common()->_get_logger();  
246    
247          #          #
248          # open Hyper Estraier database          # 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    
         my $est_config = $config->{hyperestraier} || $log->logdie("can't find 'hyperestraier' part in confguration");  
         $est_config->{database} = $database;  
         $est_config->{clean} = $clean;  
         $est_config->{label} = $db_config->{name};  
   
         my $est = new WebPAC::Output::Estraier( %{ $est_config } );  
273    
274          #          #
275          # now WebPAC::Store          # now WebPAC::Store
# Line 103  while (my ($database, $db_config) = each Line 277  while (my ($database, $db_config) = each
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");
284                  rmtree( $db_path ) || $log->warn("can't remove $db_path: $!");                  rmtree( $db_path ) || $log->warn("can't remove $db_path: $!");
285          } else {          } else {
286                  $log->debug("working on $database in $db_path");                  $log->info("working on database '$database' in $db_path");
287          }          }
288    
289          my $db = new WebPAC::Store(          my $db = new WebPAC::Store(
# Line 132  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));
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 $lookup = new WebPAC::Lookup(                  my $input_module = $config->webpac('inputs')->{$type};
318                          lookup_file => $input->{lookup},  
319                    $log->info("working on input '$input->{name}' in $input->{path} [type: $input->{type}] using $input_module",
320                            $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->{path}' [$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,
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                  my $maxmfn = $input_db->open(                  my $maxmfn = $input_db->open(
353                          path => $input->{path},                          path => $input->{path},
354                          code_page => $input->{encoding},        # database encoding                          code_page => $input->{encoding},        # database encoding
355                            %{ $input },
356                  );                  );
357    
358                  my $n = new WebPAC::Normalize::XML(                  my $report_fh;
359                  #       filter => { 'foo' => sub { shift } },                  if ($stats || $validate) {
360                          db => $db,                          my $path = "out/report/" . $database . '-' . $input->{name} . '.txt';
361                          lookup_regex => $lookup->regex,                          open($report_fh, '>', $path) || $log->logdie("can't open $path: $!");
362                          lookup => $lookup,  
363                          prefix => $input->{name},                          print $report_fh "Report for database '$database' input '$input->{name}' records ",
364                  );                                  $offset || 1, "-", $limit || $input->{limit} || $maxmfn, "\n\n";
365                            $log->info("Generating report file $path");
366                    }
367    
368                    my @norm_array = ref($input->{normalize}) eq 'ARRAY' ?
369                            @{ $input->{normalize} } : ( $input->{normalize} );
370    
371                    if ($marc_normalize) {
372                            @norm_array = ( {
373                                    path => $marc_normalize,
374                                    output => $marc_output || 'out/marc/' . $database . '-' . $input->{name} . '.marc',
375                            } );
376                    }
377    
378                    foreach my $normalize (@norm_array) {
379    
380                            my $normalize_path = $normalize->{path} || $log->logdie("can't find normalize path in config");
381    
382                            $log->logdie("Found '$normalize_path' as normalization file which isn't supported any more!") unless ( $normalize_path =~ m!\.pl$!i );
383    
384                            my $rules = read_file( $normalize_path ) or die "can't open $normalize_path: $!";
385    
386                            $log->info("Using $normalize_path for normalization...");
387    
388                            my $marc = new WebPAC::Output::MARC(
389                                    path => $normalize->{output},
390                                    lint => $marc_lint,
391                                    dump => $marc_dump,
392                            ) if ($normalize->{output});
393    
394                            # reset position in database
395                            $input_db->seek(1);
396    
397                            # generate name of config key for indexer (strip everything after -)
398                            my $indexer_config = $use_indexer;
399                            $indexer_config =~ s/^(\w+)-?.*$/$1/g if ($indexer_config);
400    
401                            foreach my $pos ( 0 ... $input_db->size ) {
402    
403                                    my $row = $input_db->fetch || next;
404    
405                                    my $mfn = $row->{'000'}->[0];
406    
407                  my $normalize_path = $input->{normalize}->{path};                                  if (! $mfn || $mfn !~ m#^\d+$#) {
408                                            $log->warn("record $pos doesn't have valid MFN but '$mfn', using $pos");
409                                            $mfn = $pos;
410                                            push @{ $row->{'000'} }, $pos;
411                                    }
412    
413                  if ($normalize_path =~ m/\.xml$/i) {  
414                          $n->open(                                  if ($validate) {
415                                  tag => $input->{normalize}->{tag},                                          if ( my $errors = $validate->validate_errors( $row, $input_db->dump ) ) {
416                                  xml_file => $input->{normalize}->{path},                                                  $log->error( "MFN $mfn validation error:\n",
417                          );                                                          $validate->report_error( $errors )
418                  } elsif ($normalize_path =~ m/\.(?:yml|yaml)$/i) {                                                  );
419                          $n->open_yaml(                                          }
420                                  path => $normalize_path,                                  }
421                                  tag => $input->{normalize}->{tag},  
422                          );                                  my $ds_config = dclone($db_config);
423                  }  
424                                    # default values -> database key
425                  foreach my $pos ( 0 ... $input_db->size ) {                                  $ds_config->{_} = $database;
426    
427                          my $row = $input_db->fetch || next;                                  # current mfn
428                                    $ds_config->{_mfn} = $mfn;
429                          my $mfn = $row->{'000'}->[0];  
430                                    # attach current input
431                          if (! $mfn || $mfn !~ m#^\d+$#) {                                  $ds_config->{input} = $input;
432                                  $log->warn("record $pos doesn't have valid MFN but '$mfn', using $pos");  
433                                  $mfn = $pos;                                  my $ds = WebPAC::Normalize::data_structure(
434                                  push @{ $row->{'000'} }, $pos;                                          row => $row,
435                                            rules => $rules,
436                                            lookup => $lookup ? $lookup->lookup_hash : undef,
437                                            config => $ds_config,
438                                            marc_encoding => 'utf-8',
439                                    );
440    
441                                    $db->save_ds(
442                                            id => $mfn,
443                                            ds => $ds,
444                                            prefix => $input->{name},
445                                    ) if ($ds && !$stats);
446    
447                                    $indexer->add(
448                                            id => $input->{name} . "/" . $mfn,
449                                            ds => $ds,
450                                            type => $config->get($indexer_config)->{type},
451                                    ) if ($indexer && $ds);
452    
453                                    if ($marc) {
454                                            my $i = 0;
455    
456                                            while (my $fields = WebPAC::Normalize::_get_marc_fields( fetch_next => 1 ) ) {
457                                                    $marc->add(
458                                                            id => $mfn . ( $i ? "/$i" : '' ),
459                                                            fields => $fields,
460                                                            leader => WebPAC::Normalize::marc_leader(),
461                                                            row => $row,
462                                                    );
463                                                    $i++;
464                                            }
465    
466                                            $log->info("Created $i instances of MFN $mfn\n") if ($i > 1);
467                                    }
468    
469                                    $total_rows++;
470                            }
471    
472                            if ($validate) {
473                                    my $errors = $validate->report;
474                                    if ($errors) {
475                                            $log->info("validation errors:\n$errors\n" );
476                                            print $report_fh "$errors\n" if ($report_fh);
477                                    }
478                          }                          }
479    
480                          my $ds = $n->data_structure($row);                          if ($stats) {
481                                    my $s = $input_db->stats;
482                                    $log->info("statistics of fields usage:\n$s");
483                                    print $report_fh "Statistics of fields usage:\n$s" if ($report_fh);
484                            }
485    
486                          $est->add(                          # close MARC file
487                                  id => $input->{name} . "/" . $mfn,                          $marc->finish if ($marc);
                                 ds => $ds,  
                                 type => $config->{hyperestraier}->{type},  
                         );  
488    
489                          $total_rows++;                          # close report
490                            close($report_fh) if ($report_fh)
491                  }                  }
492    
493          };          }
494    
495            eval { $indexer->finish } if ($indexer && $indexer->can('finish'));
496    
497          my $dt = time() - $start_t;          my $dt = time() - $start_t;
498          $log->info("$total_rows records indexed in " .          $log->info("$total_rows records ", $indexer ? "indexed " : "",
499                  sprintf("%.2f sec [%.2f rec/sec]",                  sprintf("in %.2f sec [%.2f rec/sec]",
500                          $dt, ($total_rows / $dt)                          $dt, ($total_rows / $dt)
501                  )                  )
502          );          );
503    
504          #  
505          # add Hyper Estraier links to other databases          # end forked process
506          #          if ($parallel) {
507          if (ref($db_config->{links}) eq 'ARRAY') {                  $log->info("parallel process $$ finished");
508                  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},  
                         );  
                 }  
509          }          }
510    
511  }  }
512    
513    if ($parallel) {
514            # wait all children to finish
515            sleep(1) while wait != -1;
516            $log->info("all parallel processes finished");
517    }
518    
519    #
520    # handle links or merge after indexing
521    #
522    
523    if ($merge) {
524            print $estcmd_fh 'sudo /etc/init.d/hyperestraier start',$/;
525            close($estcmd_fh);
526            chmod 0700, $estcmd_path || $log->warn("can't chmod 0700 $estcmd_path: $!");
527            system $estcmd_path;
528    } else {
529            foreach my $link (@links) {
530                    $log->logdie("coderef in link ", Dumper($link), " is ", ref($link), " and not CODE") unless (ref($link) eq 'CODE');
531                    $link->();
532            }
533    }

Legend:
Removed from v.423  
changed lines
  Added in v.699

  ViewVC Help
Powered by ViewVC 1.1.26