/[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 301 by dpavlin, Mon Dec 19 21:26:04 2005 UTC revision 627 by dpavlin, Tue Sep 5 15:14:14 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.05;  use WebPAC::Validate;
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/;
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 40  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 --only=database_name/input_filter
51    
52    reindex just single database (legacy name is --one)
53    
54    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 and dump statistics about field and subfield
64    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 54  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 $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" => \$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();
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          my $log = _new WebPAC::Common()->_get_logger();          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          # open Hyper Estraier database                  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 $est_config = $config->{hyperestraier} || $log->logdie("can't find 'hyperestraier' part in confguration");          my $indexer;
210          $est_config->{database} = $database;          if ($use_indexer) {
211    
212          my $est = new WebPAC::Output::Estraier(                  my $cfg_name = $use_indexer;
213                  %{ $est_config },                  $cfg_name =~ s/\-.*$//;
         );  
214    
215          if ($clean) {                  my $indexer_config = $config->{$cfg_name} || $log->logdie("can't find '$cfg_name' part in confguration");
216                  $log->warn("creating new empty index $database");                  $indexer_config->{database} = $database;
217                  $est->master( action => 'nodedel', name => $database );                  $indexer_config->{clean} = $clean;
218                  $est->master( action => 'nodeadd', name => $database, label => $database );                  $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                            $use_indexer = 'hyperestraier';
236    
237                    } elsif ($use_indexer eq 'kinosearch') {
238    
239                            # open KinoSearch
240                            use WebPAC::Output::KinoSearch;
241                            $indexer_config->{clean} = 1 unless (-e $indexer_config->{index_path});
242                            $indexer = new WebPAC::Output::KinoSearch( %{ $indexer_config } );
243    
244                    } else {
245                            $log->logdie("unknown use_indexer: $use_indexer");
246                    }
247    
248                    $log->logide("can't continue without valid indexer") unless ($indexer);
249          }          }
250    
251    
252            #
253            # store Hyper Estraier links to other databases
254            #
255            if (ref($db_config->{links}) eq 'ARRAY' && $use_indexer) {
256                    foreach my $link (@{ $db_config->{links} }) {
257                            if ($use_indexer eq 'hyperestraier') {
258                                    if ($merge) {
259                                            print $estcmd_fh 'sudo -u www-data estcmd merge ' . $database . ' ' . $link->{to},$/;
260                                    } else {
261                                            $log->info("saving link $database -> $link->{to} [$link->{credit}]");
262                                            push @links, sub {
263                                                    $log->info("adding link $database -> $link->{to} [$link->{credit}]");
264                                                    $indexer->add_link(
265                                                            from => $database,
266                                                            to => $link->{to},
267                                                            credit => $link->{credit},
268                                                    );
269                                            };
270                                    }
271                            } else {
272                                    $log->warn("NOT IMPLEMENTED WITH $use_indexer: adding link $database -> $link->{to} [$link->{credit}]");
273                            }
274                    }
275            }
276            next if ($only_links);
277    
278    
279          #          #
280          # now WebPAC::Store          # now WebPAC::Store
281          #          #
# Line 101  while (my ($database, $db_config) = each Line 285  while (my ($database, $db_config) = each
285          my $db_path = $config->{webpac}->{db_path} . '/' . $database;          my $db_path = $config->{webpac}->{db_path} . '/' . $database;
286    
287          if ($clean) {          if ($clean) {
288                  $log->info("creating new database $database in $db_path");                  $log->info("creating new database '$database' in $db_path");
289                  rmtree( $db_path ) || $log->warn("can't remove $db_path: $!");                  rmtree( $db_path ) || $log->warn("can't remove $db_path: $!");
290          } else {          } else {
291                  $log->info("working on $database in $db_path");                  $log->info("working on database '$database' in $db_path");
292          }          }
293    
294          my $db = new WebPAC::Store(          my $db = new WebPAC::Store(
# Line 131  while (my ($database, $db_config) = each Line 315  while (my ($database, $db_config) = each
315    
316          foreach my $input (@inputs) {          foreach my $input (@inputs) {
317    
318                    next if ($only_input && ($input->{name} !~ m#$only_input#i && $input->{type} !~ m#$only_input#i));
319    
320                  my $type = lc($input->{type});                  my $type = lc($input->{type});
321    
322                  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));
323    
324                  my $lookup = new WebPAC::Lookup(                  my $lookup;
325                          lookup_file => $input->{lookup},                  if ($input->{lookup}) {
326                  );                          $lookup = new WebPAC::Lookup(
327                                    lookup_file => $input->{lookup},
328                            );
329                            delete( $input->{lookup} );
330                    }
331    
332                  my $input_module = $config->{webpac}->{inputs}->{$type};                  my $input_module = $config->{webpac}->{inputs}->{$type};
333    
334                  $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",
335                            $input->{lookup} ? "lookup '$input->{lookup}'" : ""
336                    );
337    
338                  my $input_db = new WebPAC::Input(                  my $input_db = new WebPAC::Input(
339                          module => $input_module,                          module => $input_module,
340                          code_page => $config->{webpac}->{webpac_encoding},                          encoding => $config->{webpac}->{webpac_encoding},
341                          limit => $limit || $input->{limit},                          limit => $limit || $input->{limit},
342                          offset => $offset,                          offset => $offset,
343                          lookup => $lookup,                          lookup_coderef => sub {
344                                    my $rec = shift || return;
345                                    $lookup->add( $rec );
346                            },
347                            recode => $input->{recode},
348                            stats => $stats,
349                            modify_records => $input->{modify_records},
350                  );                  );
351                  $log->logdie("can't create input using $input_module") unless ($input);                  $log->logdie("can't create input using $input_module") unless ($input);
352    
353                  my $maxmfn = $input_db->open(                  my $maxmfn = $input_db->open(
354                          path => $input->{path},                          path => $input->{path},
355                          code_page => $input->{encoding},        # database encoding                          code_page => $input->{encoding},        # database encoding
356                            %{ $input },
357                  );                  );
358    
359                  my $n = new WebPAC::Normalize::XML(                  my @norm_array = ref($input->{normalize}) eq 'ARRAY' ?
360                  #       filter => { 'foo' => sub { shift } },                          @{ $input->{normalize} } : ( $input->{normalize} );
                         db => $db,  
                         lookup_regex => $lookup->regex,  
                         lookup => $lookup,  
                         prefix => $input->{name},  
                 );  
   
                 my $normalize_path = $input->{normalize}->{path};  
361    
362                  if ($normalize_path =~ m/\.xml$/i) {                  if ($marc_normalize) {
363                          $n->open(                          @norm_array = ( {
364                                  tag => $input->{normalize}->{tag},                                  path => $marc_normalize,
365                                  xml_file => $input->{normalize}->{path},                                  output => $marc_output || 'out/marc/' . $database . '-' . $input->{name} . '.marc',
366                          );                          } );
                 } elsif ($normalize_path =~ m/\.(?:yml|yaml)$/i) {  
                         $n->open_yaml(  
                                 path => $normalize_path,  
                                 tag => $input->{normalize}->{tag},  
                         );  
367                  }                  }
368    
369                  foreach my $pos ( 0 ... $input_db->size ) {                  foreach my $normalize (@norm_array) {
370    
371                            my $normalize_path = $normalize->{path} || $log->logdie("can't find normalize path in config");
372    
373                            $log->logdie("Found '$normalize_path' as normalization file which isn't supported any more!") unless ( $normalize_path =~ m!\.pl$!i );
374    
375                            my $rules = read_file( $normalize_path ) or die "can't open $normalize_path: $!";
376    
377                            $log->info("Using $normalize_path for normalization...");
378    
379                            my $marc = new WebPAC::Output::MARC(
380                                    path => $normalize->{output},
381                                    lint => $marc_lint,
382                                    dump => $marc_dump,
383                            ) if ($normalize->{output});
384    
385                            # reset position in database
386                            $input_db->seek(1);
387    
388                            foreach my $pos ( 0 ... $input_db->size ) {
389    
390                                    my $row = $input_db->fetch || next;
391    
392                          my $row = $input_db->fetch || next;                                  my $mfn = $row->{'000'}->[0];
393    
394                          my $mfn = $row->{'000'}->[0];                                  if (! $mfn || $mfn !~ m#^\d+$#) {
395                                            $log->warn("record $pos doesn't have valid MFN but '$mfn', using $pos");
396                                            $mfn = $pos;
397                                            push @{ $row->{'000'} }, $pos;
398                                    }
399    
400                          if (! $mfn || $mfn !~ m#^\d+$#) {  
401                                  $log->warn("record $pos doesn't have valid MFN but '$mfn', using $pos");                                  if ($validate) {
402                                  $mfn = $pos;                                          my @errors = $validate->validate_errors( $row );
403                                  push @{ $row->{'000'} }, $pos;                                          $log->error( "MFN $mfn validation errors:\n", join("\n", @errors) ) if (@errors);
404                                    }
405    
406                                    my $ds_config = dclone($db_config);
407    
408                                    # default values -> database key
409                                    $ds_config->{_} = $database;
410    
411                                    # current mfn
412                                    $ds_config->{_mfn} = $mfn;
413    
414                                    # attach current input
415                                    $ds_config->{input} = $input;
416    
417                                    my $ds = WebPAC::Normalize::data_structure(
418                                            row => $row,
419                                            rules => $rules,
420                                            lookup => $lookup ? $lookup->lookup_hash : undef,
421                                            config => $ds_config,
422                                            marc_encoding => 'utf-8',
423                                    );
424    
425                                    $db->save_ds(
426                                            id => $mfn,
427                                            ds => $ds,
428                                            prefix => $input->{name},
429                                    ) if ($ds && !$stats);
430    
431                                    $indexer->add(
432                                            id => $input->{name} . "/" . $mfn,
433                                            ds => $ds,
434                                            type => $config->{$use_indexer}->{type},
435                                    ) if ($indexer && $ds);
436    
437                                    if ($marc) {
438                                            my $i = 0;
439    
440                                            while (my $fields = WebPAC::Normalize::_get_marc_fields( fetch_next => 1 ) ) {
441                                                    $marc->add(
442                                                            id => $mfn . ( $i ? "/$i" : '' ),
443                                                            fields => $fields,
444                                                            leader => WebPAC::Normalize::marc_leader(),
445                                                            row => $row,
446                                                    );
447                                                    $i++;
448                                            }
449    
450                                            $log->info("Created $i instances of MFN $mfn\n") if ($i > 1);
451                                    }
452    
453                                    $total_rows++;
454                          }                          }
455    
456                          my $ds = $n->data_structure($row);                          $log->info("statistics of fields usage:\n", $input_db->stats) if ($stats);
457    
458                          $est->add(                          # close MARC file
459                                  id => $input->{name} . "/" . $mfn,                          $marc->finish if ($marc);
                                 ds => $ds,  
                                 type => $config->{hyperestraier}->{type},  
                         );  
460    
                         $total_rows++;  
461                  }                  }
462    
463          };          }
464    
465          $log->info("$total_rows records indexed");          eval { $indexer->finish } if ($indexer && $indexer->can('finish'));
466    
467          #          my $dt = time() - $start_t;
468          # add Hyper Estraier links to other databases          $log->info("$total_rows records ", $indexer ? "indexed " : "",
469          #                  sprintf("in %.2f sec [%.2f rec/sec]",
470          if (ref($db_config->{links}) eq 'ARRAY') {                          $dt, ($total_rows / $dt)
471                  foreach my $link (@{ $db_config->{links} }) {                  )
472                          $log->info("adding link $database -> $link->{to} [$link->{credit}]");          );
473                          $est->add_link(  
474                                  from => $database,  
475                                  to => $link->{to},          # end forked process
476                                  credit => $link->{credit},          if ($parallel) {
477                          );                  $log->info("parallel process $$ finished");
478                  }                  exit(0);
479          }          }
480    
481  }  }
482    
483    if ($parallel) {
484            # wait all children to finish
485            sleep(1) while wait != -1;
486            $log->info("all parallel processes finished");
487    }
488    
489    #
490    # handle links or merge after indexing
491    #
492    
493    if ($merge) {
494            print $estcmd_fh 'sudo /etc/init.d/hyperestraier start',$/;
495            close($estcmd_fh);
496            chmod 0700, $estcmd_path || $log->warn("can't chmod 0700 $estcmd_path: $!");
497            system $estcmd_path;
498    } else {
499            foreach my $link (@links) {
500                    $log->logdie("coderef in link ", Dumper($link), " is ", ref($link), " and not CODE") unless (ref($link) eq 'CODE');
501                    $link->();
502            }
503    }

Legend:
Removed from v.301  
changed lines
  Added in v.627

  ViewVC Help
Powered by ViewVC 1.1.26