Changeset 113

Show
Ignore:
Timestamp:
10/21/06 17:49:36 (7 years ago)
Author:
max
Message:

Prevent broken C1 grabbers from causing infinite loops.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • shepherd

    r112 r113  
    118118my $days = 7; 
    119119my $timeslice; 
     120my $grabbed; 
    120121my $gmt_offset; 
    121122my $grabber_found_all_data; 
     
    276277        { 
    277278            print "CAT1 grabber: grabbing timeslice.\n" if ($debug); 
     279 
     280            record_requested_chandays($grabber, $timeslice); 
     281 
    278282            if ($timeslice->{start} != 1) 
    279283            { 
     
    342346 
    343347            my $missing_after = convert_chandays_to_list(detect_missing_data()); 
    344             # print "Missing before: " . Dumper($missing_before) . "\nMissing after:" . Dumper($missing_after); 
     348#          print "Missing before: " . Dumper($missing_before) . "\nMissing after:" . Dumper($missing_after); 
    345349            my $list = List::Compare->new($missing_before, $missing_after); 
    346350            my @grabbed = $list->get_symmetric_difference(); 
     
    393397    # score grabbers 
    394398    my $total = score_grabbers(); 
    395     return undef unless ($total); 
    396399     
    397400    if ($debug) 
    398401    { 
    399402        print "Grabber selection probabilities:\n"; 
     403        my $perc; 
    400404        foreach (sort { $gscore->{$b} <=> $gscore->{$a} } keys %$gscore) 
    401405        { 
     406            $perc = 100 * ($total ? $gscore->{$_} / $total : 0); 
    402407            printf "%25s %6.1f%% %12s\n",  
    403                    $_, 100 * $gscore->{$_} / $total, "($gscore->{$_} pts)"; 
    404         } 
    405     } 
    406  
    407     return undef unless (scalar keys %$gscore); 
     408                   $_, $perc, "($gscore->{$_} pts)"; 
     409        } 
     410    } 
     411 
     412    return undef unless ($total); 
    408413 
    409414    my $r = int(rand($total)); 
     
    415420        if ($r >= $c and $r < ($c + $gscore->{$grabber})) 
    416421        { 
    417             delete $gscore->{$grabber}; 
    418422            print "Selected $grabber.\n" if ($debug); 
    419423            if ($grabber =~ /(.*) \[cache\]/) 
     
    454458    my $missing = detect_missing_data(); 
    455459 
    456     calculate_best_timeslice($missing); 
     460    $timeslice = calculate_best_timeslice($missing); 
    457461     
    458462    print "Best timeslice: " . Dumper($timeslice) . "\n" if ($debug); 
     
    476480        if ($cat == 1) 
    477481        { 
    478             $key = $missing_slice; 
     482            $key = cut_down($grabber, $missing_slice); 
    479483            print "Grabber $grabber is Category 1: comparing capability to best timeslice.\n" if ($debug); 
    480484        } 
     
    591595    my $hits = 0; 
    592596 
     597#    print "Find cache hits in: " . Dumper($missing); 
    593598    foreach my $day (keys %$missing) 
    594599    { 
     
    596601        foreach my $ch (@{$missing->{$day}}) 
    597602        { 
    598             $hits++ if (grep(/^$date:$ch$/, @{$components->{$grabber}->{cached}})); 
     603            if (grep(/^$date:$ch$/, @{$components->{$grabber}->{cached}})) 
     604            { 
     605                $hits++; 
     606                print "Hit: $day:$ch\n" if ($debug); 
     607            } 
    599608        } 
    600609    } 
     
    616625    my $timeslots_per_day = (24 * 60 * 60) / $policy{timeslot_size}; 
    617626 
    618     # print "Channel data:\n" . Dumper($channel_data); 
    619627    foreach my $ch (keys %$channels) 
    620628    { 
     
    656664} 
    657665 
     666# Takes a hash of what's missing in the format: 
     667#   { '1' => [ 'ABC', 'SBS' ], '2' => [ 'ABC' ], ... } 
     668# and sets $timeslice to the biggest 'slice' of that. 
     669# For example, the biggest slice of the above is days 1 -2 of ABC. 
    658670sub calculate_best_timeslice 
    659671{ 
     
    661673 
    662674    my ($overlap, $a); 
    663     $timeslice = { 'chandays' => 0 }; 
     675    my $slice = { 'chandays' => 0 }; 
    664676    foreach my $day (1 .. $days) 
    665677    { 
    666         consider_slice($day, $day, @{$missing->{$day}}); 
     678        consider_slice($slice, $day, $day, @{$missing->{$day}}); 
    667679        $overlap = $missing->{$day}; 
    668680        foreach my $nextday (($day + 1) .. $days) 
     
    670682            last unless ($missing->{$nextday}); 
    671683            $a = Algorithm::Diff::LCS($overlap, $missing->{$nextday}); 
    672             # print "Overlap: " . Dumper($a); 
    673684            last unless ($a and @{$a}); 
    674             consider_slice($day, $nextday, @{$a}); 
     685            consider_slice($slice, $day, $nextday, @{$a}); 
    675686            $overlap = $a; 
    676687        } 
    677688    } 
     689    return $slice; 
    678690} 
    679691 
    680692sub consider_slice 
    681693{ 
    682     my ($startday, $stopday, @chans) = @_; 
     694    my ($slice, $startday, $stopday, @chans) = @_; 
    683695 
    684696    my $challenger = ($stopday - $startday + 1) * scalar(@chans); 
    685     return unless ($challenger > $timeslice->{chandays}); 
     697    return unless ($challenger > $slice->{chandays}); 
    686698 
    687699    # We have a winner! 
    688     $timeslice->{start} = $startday; 
    689     $timeslice->{stop} = $stopday; 
    690     $timeslice->{chans} = [ @chans ]; 
    691     $timeslice->{chandays} = $challenger; 
    692 } 
    693  
     700    $slice->{start} = $startday; 
     701    $slice->{stop} = $stopday; 
     702    $slice->{chans} = [ @chans ]; 
     703    $slice->{chandays} = $challenger; 
     704} 
     705 
     706# Turns the current $timeslice into a missing-style hash 
     707# (i.e. { '1' => [ 'ABC', 'SBS' ], '2' => ... 
    694708sub create_missing_slice 
    695709{ 
     
    703717} 
    704718 
     719# Record what a cacheable C1 grabber has just retrieved for us, 
     720# so we know next time that this data can be grabbed quickly. 
    705721sub record_cached 
    706722{ 
     
    732748} 
    733749 
    734 # Takes a 'missing' hash and returns it as a list like this: 
     750# Takes a missing-style hash and returns it as a list like this: 
    735751# ( "20061018:ABC", "20061018:Seven", ... ) 
    736752sub convert_chandays_to_list 
     
    751767} 
    752768 
     769# If we're about to re-try a grabber, make sure that we're not asking 
     770# it for the same data. That is, prevent a broken C1 grabber causing 
     771# an infinite loop. 
     772sub record_requested_chandays 
     773{ 
     774    my ($grabber, $slice) = @_; 
     775 
     776    print "Recording timeslice request; will not request these chandays from $grabber again.\n" if ($debug); 
     777 
     778    my @requested; 
     779    for my $day ($slice->{start} .. $slice->{stop}) 
     780    { 
     781        foreach my $ch (@{$slice->{chans}}) 
     782        { 
     783            push @requested, "$day:$ch"; 
     784        } 
     785    } 
     786    if ($grabbed->{$grabber}) 
     787    { 
     788        push @{$grabbed->{$grabber}}, @requested; 
     789    } 
     790    else 
     791    { 
     792        $grabbed->{$grabber} = [ @requested ]; 
     793    } 
     794} 
     795 
     796# If this grabber has been called previously, remove those chandays 
     797# from the current request -- we don't want to ask it over and over 
     798# for a timeslice that it has already failed to provide. 
     799sub cut_down 
     800{ 
     801    my ($grabber, $slice) = @_; 
     802 
     803    return $slice unless ($grabbed->{$grabber}); 
     804 
     805    if ($debug) 
     806    { 
     807        print "Grabber $grabber has been called previously; removing " . 
     808              "requested chandays from timeslice.\n"; 
     809    } 
     810 
     811    my $newslice = {}; 
     812    foreach my $day (keys %$slice) 
     813    { 
     814        my @chans; 
     815        foreach my $ch (@{$slice->{$day}}) 
     816        { 
     817            unless (grep(/$day:$ch/, @{$grabbed->{$grabber}})) 
     818            { 
     819                push (@chans, $ch); 
     820            } 
     821        } 
     822        if (@chans) 
     823        { 
     824            $newslice->{$day} = [ @chans ]; 
     825        } 
     826    } 
     827    return $newslice; 
     828} 
    753829 
    754830# interpret xmltv data from this grabber/postprocessor