Skip to content

Commit 2bd3296

Browse files
committed
Bug 1180570 - store attachment size in the database
1 parent 425d780 commit 2bd3296

File tree

4 files changed

+24
-62
lines changed

4 files changed

+24
-62
lines changed

Bugzilla/Attachment.pm

Lines changed: 10 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ use constant DB_COLUMNS => qw(
8989
mimetype
9090
modification_time
9191
submitter_id
92+
attach_size
9293
);
9394

9495
use constant REQUIRED_FIELD_MAP => {
@@ -359,45 +360,14 @@ sub data {
359360
360361
=item C<datasize>
361362
362-
the length (in characters) of the attachment content
363+
the length (in bytes) of the attachment content
363364
364365
=back
365366
366367
=cut
367368

368-
# datasize is a property of the data itself, and it's unclear whether we should
369-
# expose it at all, since you can easily derive it from the data itself: in TT,
370-
# attachment.data.size; in Perl, length($attachment->{data}). But perhaps
371-
# it makes sense for performance reasons, since accessing the data forces it
372-
# to get retrieved from the database/filesystem and loaded into memory,
373-
# while datasize avoids loading the attachment into memory, calling SQL's
374-
# LENGTH() function or stat()ing the file instead. I've left it in for now.
375-
376369
sub datasize {
377-
my $self = shift;
378-
return $self->{datasize} if defined $self->{datasize};
379-
380-
# If we have already retrieved the data, return its size.
381-
return length($self->{data}) if exists $self->{data};
382-
383-
$self->{datasize} =
384-
Bugzilla->dbh->selectrow_array("SELECT LENGTH(thedata)
385-
FROM attach_data
386-
WHERE id = ?",
387-
undef, $self->id) || 0;
388-
389-
# If there's no attachment data in the database, either the attachment
390-
# is stored in a local file, and so retrieve its size from the file,
391-
# or the attachment has been deleted.
392-
unless ($self->{datasize}) {
393-
if (open(AH, '<', $self->_get_local_filename())) {
394-
binmode AH;
395-
$self->{datasize} = (stat(AH))[7];
396-
close(AH);
397-
}
398-
}
399-
400-
return $self->{datasize};
370+
return $_[0]->{attach_size};
401371
}
402372

403373
=over
@@ -566,18 +536,18 @@ sub _check_data {
566536
my ($invocant, $params) = @_;
567537

568538
my $data = $params->{data};
569-
$params->{filesize} = ref $data ? -s $data : length($data);
539+
$params->{attach_size} = ref $data ? -s $data : length($data);
570540

571541
Bugzilla::Hook::process('attachment_process_data', { data => \$data,
572542
attributes => $params });
573543

574-
$params->{filesize} || ThrowUserError('zero_length_file');
544+
$params->{attach_size} || ThrowUserError('zero_length_file');
575545
# Make sure the attachment does not exceed the maximum permitted size.
576546
my $max_size = max(Bugzilla->params->{'maxlocalattachment'} * 1048576,
577547
Bugzilla->params->{'maxattachmentsize'} * 1024);
578548

579-
if ($params->{filesize} > $max_size) {
580-
my $vars = { filesize => sprintf("%.0f", $params->{filesize}/1024) };
549+
if ($params->{attach_size} > $max_size) {
550+
my $vars = { filesize => sprintf("%.0f", $params->{attach_size}/1024) };
581551
ThrowUserError('file_too_large', $vars);
582552
}
583553
return $data;
@@ -703,16 +673,6 @@ sub get_attachments_by_bug {
703673
foreach my $attachment (@$attachments) {
704674
$attachment->{attacher} = $user_map{$attachment->{submitter_id}};
705675
}
706-
707-
# Preload datasizes.
708-
my $sizes =
709-
$dbh->selectall_hashref('SELECT attach_id, LENGTH(thedata) AS datasize
710-
FROM attachments LEFT JOIN attach_data ON attach_id = id
711-
WHERE bug_id = ?',
712-
'attach_id', undef, $bug->id);
713-
714-
# Force the size of attachments not in the DB to be recalculated.
715-
$_->{datasize} = $sizes->{$_->id}->{datasize} || undef foreach @$attachments;
716676
}
717677
return $attachments;
718678
}
@@ -842,13 +802,12 @@ sub create {
842802
my $bug = delete $params->{bug};
843803
$params->{bug_id} = $bug->id;
844804
my $data = delete $params->{data};
845-
my $size = delete $params->{filesize};
846805

847806
my $attachment = $class->insert_create_data($params);
848807
my $attachid = $attachment->id;
849808

850809
# The file is too large to be stored in the DB, so we store it locally.
851-
if ($size > Bugzilla->params->{'maxattachmentsize'} * 1024) {
810+
if ($params->{attach_size} > Bugzilla->params->{'maxattachmentsize'} * 1024) {
852811
my $attachdir = bz_locations()->{'attachdir'};
853812
my $hash = ($attachid % 100) + 100;
854813
$hash =~ s/.*(\d\d)$/group.$1/;
@@ -966,8 +925,8 @@ sub remove_from_db {
966925
$dbh->do('DELETE FROM flags WHERE ' . $dbh->sql_in('id', $flag_ids))
967926
if @$flag_ids;
968927
$dbh->do('DELETE FROM attach_data WHERE id = ?', undef, $self->id);
969-
$dbh->do('UPDATE attachments SET mimetype = ?, ispatch = ?, isobsolete = ?
970-
WHERE attach_id = ?', undef, ('text/plain', 0, 1, $self->id));
928+
$dbh->do('UPDATE attachments SET mimetype = ?, ispatch = ?, isobsolete = ?, attach_size = ?
929+
WHERE attach_id = ?', undef, ('text/plain', 0, 1, 0, $self->id));
971930
$dbh->bz_commit_transaction();
972931

973932
# As we don't call SUPER->remove_from_db we need to manually clear

Bugzilla/Install/DB.pm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ sub update_table_definitions {
730730
$dbh->bz_add_index('user_api_keys', 'user_api_keys_user_id_app_id_idx',
731731
[qw(user_id app_id)]);
732732

733-
# _add_attach_size();
733+
_add_attach_size();
734734

735735
################################################################
736736
# New --TABLE-- changes should go *** A B O V E *** this point #

extensions/Push/t/ReviewBoard.t

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,17 @@ my $dbh = Bugzilla->dbh;
9595
$dbh->bz_start_transaction;
9696
my $timestamp = $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
9797
my $bug = Bugzilla::Bug->new({id => 9000});
98-
my $attachment = Bugzilla::Attachment->create(
99-
{ bug => $bug,
100-
creation_ts => $timestamp,
101-
data => $data,
102-
filesize => length $data,
103-
description => "rblink.txt",
104-
filename => "rblink.txt",
105-
isprivate => 1, ispatch => 0,
106-
mimetype => 'text/x-review-board-request'});
98+
my $attachment = Bugzilla::Attachment->create({
99+
bug => $bug,
100+
creation_ts => $timestamp,
101+
data => $data,
102+
attach_size => length($data),
103+
description => "rblink.txt",
104+
filename => "rblink.txt",
105+
isprivate => 1,
106+
ispatch => 0,
107+
mimetype => 'text/x-review-board-request'
108+
});
107109
diag "".$attachment->id;
108110
$dbh->bz_commit_transaction;
109111

scripts/sanitizeme.pl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,9 @@ sub delete_sensitive_user_data {
210210

211211
sub delete_attachment_data {
212212
# Delete unnecessary attachment data.
213-
print "Removing attachment data to preserve disk space...\n";
213+
print "Removing attachment data...\n";
214214
$dbh->do("UPDATE attach_data SET thedata = ''");
215+
$dbh->do("UPDATE attachments SET attach_size = 0");
215216
}
216217

217218
sub delete_bug_user_last_visit {

0 commit comments

Comments
 (0)