Changeset 1322

Show
Ignore:
Timestamp:
10/17/09 08:28:02 (6 weeks ago)
Author:
dormando
Message:

Fix create_close race condition

If two create_close requests are send, and one reads the tempfile, writes the
file row to the db, then gets hung before removing the tempfile... The second
one could potentially trigger its own eventual deletion.

From ptr <pipegeek@…>

Location:
trunk/server/lib/MogileFS
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • trunk/server/lib/MogileFS/Store.pm

    r1317 r1322  
    10231023sub delete_tempfile_row { 
    10241024    my ($self, $fidid) = @_; 
    1025     $self->dbh->do("DELETE FROM tempfile WHERE fid=?", undef, $fidid); 
     1025    my $rv = $self->dbh->do("DELETE FROM tempfile WHERE fid=?", undef, $fidid); 
    10261026    $self->condthrow; 
     1027    return $rv; 
     1028} 
     1029 
     1030# Load the specified tempfile, then delete it.  If we succeed, we were 
     1031# here first; otherwise, someone else beat us here (and we return undef) 
     1032sub delete_and_return_tempfile_row { 
     1033    my ($self, $fidid) = @_; 
     1034    my $rv = $self->tempfile_row_from_fid($fidid); 
     1035    my $rows_deleted = $self->delete_tempfile_row($fidid); 
     1036    return $rv if ($rows_deleted > 0); 
    10271037} 
    10281038 
  • trunk/server/lib/MogileFS/Worker/Query.pm

    r1300 r1322  
    366366    my $sto = Mgd::get_store(); 
    367367 
    368     # find the temp file we're closing and making real 
    369     my $trow = $sto->tempfile_row_from_fid($fidid) or 
     368    # find the temp file we're closing and making real.  If another worker 
     369    # already has it, bail out---the client closed it twice. 
     370    my $trow = $sto->delete_and_return_tempfile_row($fidid) or 
    370371        return $self->err_line("no_temp_file"); 
    371372 
     
    381382    my $old_fid = MogileFS::FID->new_from_dmid_and_key($dmid, $key); 
    382383    if ($old_fid) { 
     384        # Fail if a file already exists for this fid.  Should never 
     385        # happen, as it should not be possible to close a file twice. 
     386        return $self->err_line("fid_exists") 
     387            unless $old_fid->{fidid} != $fidid; 
     388 
    383389        $old_fid->delete; 
    384390    } 
     
    412418    # mark it as needing replicating: 
    413419    $fid->enqueue_for_replication(from_device => $devid); 
    414     $sto->delete_tempfile_row($fidid); 
    415420 
    416421    if ($fid->update_devcount) { 
     
    15461551        'no_ip' => "IP required to create host", 
    15471552        'no_port' => "Port required to create host", 
     1553        'no_temp_file' => "No tempfile or file already closed", 
    15481554        'none_match' => "No keys match that pattern and after-value (if any).", 
    15491555        'plugin_aborted' => "Action aborted by plugin",