Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Bugzilla/Memcached.pm
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,13 @@ sub should_rate_limit {
$memcached->add($key, 0, $rate_seconds + 1);
my $tokens = $memcached->get_multi(@keys);
my $cas = $memcached->gets($key);

# gets() returns undef when memcached is unreachable (or the key expired
# between the add and the gets). Don't let $cas->[1]++ autovivify an
# arrayref holding an undef cas id, which would then be passed to cas().
# Fail open: no working memcached means no rate limiting.
return 0 unless ref $cas eq 'ARRAY' && defined $cas->[0];

$tokens->{$key} = $cas->[1]++;
return 1 if sum(values %$tokens) >= $rate_max;
return 0 if $memcached->cas($key, @$cas, $rate_seconds + 1);
Expand Down
61 changes: 32 additions & 29 deletions extensions/BMO/lib/Reports/Attention.pm
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ sub critical_assigned_bugs {
my $dbh = Bugzilla->dbh;

# Preselected values for inserting into SQL
my $cache = Bugzilla->process_cache->{attention};
my $cache = Bugzilla->request_cache->{attention};
my $keyword_id = $cache->{sec_critical_id};
my $class_ids = join ',', @{$cache->{classification_ids}};
my $bug_states = join ',', map { $dbh->quote($_) } BUG_STATE_OPEN;
Expand Down Expand Up @@ -205,7 +205,7 @@ sub critical_needinfo_bugs {
return [] if !exists $flags->{tracking};

# Preselected values for inserting into SQL
my $cache = Bugzilla->process_cache->{attention};
my $cache = Bugzilla->request_cache->{attention};
my $needinfo_id = $cache->{needinfo_flag_id};
my $keyword_id = $cache->{sec_critical_id};
my $class_ids = join ',', @{$cache->{classification_ids}};
Expand Down Expand Up @@ -282,7 +282,7 @@ sub important_assigned_bugs {
return [] if !exists $flags->{status};

# Preselected values for inserting into SQL
my $cache = Bugzilla->process_cache->{attention};
my $cache = Bugzilla->request_cache->{attention};
my $class_ids = join ',', @{$cache->{classification_ids}};
my $bug_states = join ',', map { $dbh->quote($_) } BUG_STATE_OPEN;
my $nightly_flag_id = $flags->{status}->{nightly}->flag_id;
Expand Down Expand Up @@ -324,7 +324,7 @@ sub important_needinfo_bugs {
my $dbh = Bugzilla->dbh;

# Cached values for inserting into SQL
my $cache = Bugzilla->process_cache->{attention};
my $cache = Bugzilla->request_cache->{attention};
my $needinfo_id = $cache->{needinfo_flag_id};
my $class_ids = join ',', @{$cache->{classification_ids}};
my $keyword_id = $cache->{sec_high_id};
Expand Down Expand Up @@ -358,7 +358,7 @@ sub other_needinfo_bugs {
my $dbh = Bugzilla->dbh;

# Cached values for inserting into SQL
my $cache = Bugzilla->process_cache->{attention};
my $cache = Bugzilla->request_cache->{attention};
my $needinfo_id = $cache->{needinfo_flag_id};
my $class_ids = join ',', @{$cache->{classification_ids}};

Expand All @@ -374,7 +374,7 @@ sub other_needinfo_bugs {
AND bugs.bug_severity NOT IN ('S1','S2')
AND (keywords.keywordid IS NULL OR keywords.keywordid NOT IN (?, ?))
AND (bug_group_map.group_id IS NULL OR bug_group_map.group_id NOT IN ("
. join ',', @{$cache->{sec_group_ids}} . '))
. (join ',', @{$cache->{sec_group_ids}}) . '))
Comment thread
dklawren marked this conversation as resolved.
ORDER BY bugs.delta_ts, bugs.bug_id';

my $bugs = get_bug_list($query, $user->id, $user->id, $cache->{sec_high_id},
Expand All @@ -396,42 +396,45 @@ sub report {
= $input->{who} ? Bugzilla::User->check({name => $input->{who}}) : $user;
$vars->{who} = $who->login;

# Create a global seen list of bugs (if not yet exists) to make sure
# we do not show a bug more than once across all lists. Request cache
# lasts for only this request.
my $request_cache = Bugzilla->request_cache;
$request_cache->{attention} = {};
$request_cache->{attention}->{global_seen} = {};

my $dbh = Bugzilla->dbh;

# Here we load some values into cache that will be used later
# by the various queries. Process cache lasts til server restart.
my $process_cache = Bugzilla->process_cache->{attention} = {};

# classifications
$process_cache->{classification_ids} ||= $dbh->selectcol_arrayref('
# Set up the cache used by the various queries below. It holds a global
# seen list of bugs, so we do not show a bug more than once across all
# lists, along with values interpolated into the queries. Request cache
# lasts for this request only, so a keyword, flag type or security group
# added mid-session is picked up on the next page load rather than at
# the next server restart.
my $lookup_cache = Bugzilla->request_cache->{attention}
= {global_seen => {}};

# classifications. As with the security groups below, fall back to a
# non-existent id if none are found so the IN () clauses built from this
# list stay valid SQL and simply match nothing.
my $classification_ids = $dbh->selectcol_arrayref('
SELECT id
FROM classifications
WHERE name IN (' . join(', ', map { $dbh->quote($_) } CLASSIFICATIONS) . ')');
$lookup_cache->{classification_ids}
= @{$classification_ids} ? $classification_ids : [0];

# needinfo flag
$process_cache->{needinfo_flag_id} ||= $dbh->selectrow_array("
$lookup_cache->{needinfo_flag_id} = $dbh->selectrow_array("
SELECT id FROM flagtypes WHERE name = 'needinfo'");

# keyword ids
$process_cache->{sec_critical_id} ||= $dbh->selectrow_array("
$lookup_cache->{sec_critical_id} = $dbh->selectrow_array("
SELECT id FROM keyworddefs WHERE name = 'sec-critical'");
$process_cache->{sec_high_id} ||= $dbh->selectrow_array("
$lookup_cache->{sec_high_id} = $dbh->selectrow_array("
SELECT id FROM keyworddefs WHERE name = 'sec-high'");
$process_cache->{regression_id} ||= $dbh->selectrow_array("
SELECT id FROM keyworddefs WHERE name = 'regression'");

# Get a list of group ids that end in -security
$process_cache->{sec_group_ids}
||= $dbh->selectcol_arrayref('SELECT id FROM '
# Get a list of group ids that end in -security. Fall back to a
# non-existent id if there are none, so the IN () clauses built from
# this list stay valid SQL and simply match nothing.
my $sec_group_ids
= $dbh->selectcol_arrayref('SELECT id FROM '
. $dbh->quote_identifier('groups')
. ' WHERE name LIKE \'%-security\'');
$lookup_cache->{sec_group_ids} = @{$sec_group_ids} ? $sec_group_ids : [0];

# build bug lists
$vars->{critical_needinfo_bugs} = critical_needinfo_bugs($who);
Expand All @@ -443,8 +446,8 @@ sub report {
# count number of unique bugs
my %bug_ids;
foreach my $name (qw(
s1_bugs sec_crit_bugs critical_needinfo_bugs s2_bugs
sec_high_bugs important_needinfo_bugs other_needinfo_bugs
critical_needinfo_bugs critical_assigned_bugs important_needinfo_bugs
important_assigned_bugs other_needinfo_bugs
))
{
foreach my $bug (@{$vars->{$name}}) {
Expand Down