IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Mar 29, 2009, 6:15:31 PM (17 years ago)
Author:
beaumont
Message:

merged with head

Location:
branches/cnb_branches/cnb_branch_20090301
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/cnb_branches/cnb_branch_20090301

  • branches/cnb_branches/cnb_branch_20090301/Nebulous-Server/Changes

    r20155 r23594  
    11Revision history for Nebulous
     2
     30.17
     4    - retry database transactions when a deadlock is detected
    25
    360.16
  • branches/cnb_branches/cnb_branch_20090301/Nebulous-Server/bin/neb-admin

    r23352 r23594  
    152152       
    153153    exit unless scalar @rows;
     154   
     155    # compare number of responses to limit below
     156    my $Npending = @rows;
    154157
    155158    print "replicatePending MULTI\n\n";
     
    198201    }
    199202
    200     return 1;
     203    # use a different exit status if we hit the limit (likely more files pending)
     204    if ($Npending == $limit) {
     205        exit 1;
     206    }
     207    exit 0;
    201208}
    202 
    203209
    204210sub removal
  • branches/cnb_branches/cnb_branch_20090301/Nebulous-Server/lib/Nebulous/Server.pm

    r20990 r23594  
    163163
    164164    my $uri;
    165     eval {
    166         {
    167             # create storage_object
    168             my $query = $db->prepare_cached( $sql->new_object );
    169             $query->execute('NULL', $key->path);
    170         }
    171 
    172         my $so_id;
    173         {
    174             # get object ID
    175             my $query = $db->prepare_cached( $sql->last_insert_id );
    176             $query->execute;
    177             ($so_id) = $query->fetchrow_array;
    178             # XXX finish seems to be required when using LAST_INSERT_ID() or we
    179             # get a warning about the stmt handling still be active the next
    180             # time LAST_INSERT_ID() is invoked
    181             $query->finish;
    182         }
    183 
    184         {
    185             # create storage_object_attr
    186             my $query = $db->prepare_cached( $sql->new_object_attr );
    187             $query->execute($so_id);
    188         }
    189 
    190         {
    191            
    192             # create instance with no URI
     165TRANS: while (1) {
     166        eval {
     167            {
     168                # create storage_object
     169                my $query = $db->prepare_cached( $sql->new_object );
     170                $query->execute('NULL', $key->path);
     171            }
     172
     173            my $so_id;
     174            {
     175                # get object ID
     176                my $query = $db->prepare_cached( $sql->last_insert_id );
     177                $query->execute;
     178                ($so_id) = $query->fetchrow_array;
     179                # XXX finish seems to be required when using LAST_INSERT_ID() or we
     180                # get a warning about the stmt handling still be active the next
     181                # time LAST_INSERT_ID() is invoked
     182                $query->finish;
     183            }
     184
     185            {
     186                # create storage_object_attr
     187                my $query = $db->prepare_cached( $sql->new_object_attr );
     188                $query->execute($so_id);
     189            }
     190
     191            {
     192               
     193                # create instance with no URI
    193194#            my $query = $db->prepare_cached( $sql->new_instance );
    194             my $query = $db->prepare_cached( $sql->new_object_instance );
    195             $query->execute($vol_id);
    196         }
    197 
    198         my $ins_id;
    199         {
    200             # get instance ID
    201             my $query = $db->prepare_cached( $sql->last_insert_id );
    202             $query->execute;
    203             ($ins_id) = $query->fetchrow_array;
    204             # XXX finish seems to be required when using LAST_INSERT_ID() or we
    205             # get a warning about the stmt handling still be active the next
    206             # time LAST_INSERT_ID() is invoked
    207             $query->finish;
    208         }
    209 
    210         # Unfortunately, since we want to use the instance row's ID as part of the
    211         # actual on disk file name we can't try to create the file until after
    212         # we've create both a new storage_storage object and instance.
    213 
    214         # TODO add some stuff here to retry if unsucessful
    215         $uri = $self->_create_empty_instance_file($key->path, $so_id, $ins_id, $vol_path, $vol_xattr);
    216         $log->debug("created $uri on volume ID: $vol_id");
    217 
    218         {
    219             # update the instance with URI & vol_id that the file is on
    220             my $query = $db->prepare_cached( $sql->update_instance_uri );
    221             # vol_id, uri, ins_id
    222             $query->execute($vol_id, "$uri", $ins_id);
    223         }
    224 
    225         $db->commit;
    226         $log->debug("commit");
    227     };
    228     if ($@) {
     195                my $query = $db->prepare_cached( $sql->new_object_instance );
     196                $query->execute($vol_id);
     197            }
     198
     199            my $ins_id;
     200            {
     201                # get instance ID
     202                my $query = $db->prepare_cached( $sql->last_insert_id );
     203                $query->execute;
     204                ($ins_id) = $query->fetchrow_array;
     205                # XXX finish seems to be required when using LAST_INSERT_ID() or we
     206                # get a warning about the stmt handling still be active the next
     207                # time LAST_INSERT_ID() is invoked
     208                $query->finish;
     209            }
     210
     211            # Unfortunately, since we want to use the instance row's ID as part of the
     212            # actual on disk file name we can't try to create the file until after
     213            # we've create both a new storage_storage object and instance.
     214
     215            # TODO add some stuff here to retry if unsucessful
     216            $uri = $self->_create_empty_instance_file($key->path, $so_id, $ins_id, $vol_path, $vol_xattr);
     217            $log->debug("created $uri on volume ID: $vol_id");
     218
     219            {
     220                # update the instance with URI & vol_id that the file is on
     221                my $query = $db->prepare_cached( $sql->update_instance_uri );
     222                # vol_id, uri, ins_id
     223                $query->execute($vol_id, "$uri", $ins_id);
     224            }
     225
     226            $db->commit;
     227            $log->debug("commit");
     228        };
     229        if ($@) {
    229230#        and not $key->soft_volume
    230         $db->rollback;
    231         $log->debug("rollback");
    232         $log->logdie("error: $@");
     231            $db->rollback;
     232            $log->debug("rollback");
     233            if ($@ =~ /Deadlock found/) {
     234                $log->warn("database deadlock retrying transaction: $@");
     235                redo TRANS;
     236            }
     237            $log->logdie("error: $@");
     238        }
     239        last;
    233240    }
    234241
     
    269276    $newkey = parse_neb_key($newkey);
    270277
    271     eval {
    272         # rename storage_object
    273         my $query = $db->prepare_cached($sql->rename_object);
    274         # this SQL statment takes the new key name as the first param
    275         my $rows = $query->execute($newkey->path, $key->path);
    276 
    277         # if we affected more then one row something very bad has happened.
    278         unless ($rows == 1) {
    279             $query->finish;
    280             $log->logdie("affected row count is $rows instead of 1");
    281         }
    282 
    283         $db->commit;
    284         $log->debug("commit");
    285     };
    286     if ($@) {
    287         $db->rollback;
    288         $log->debug("rollback");
    289         $log->logdie("database error: $@");
    290     }
     278TRANS: while (1) {
     279        eval {
     280            # rename storage_object
     281            my $query = $db->prepare_cached($sql->rename_object);
     282            # this SQL statment takes the new key name as the first param
     283            my $rows = $query->execute($newkey->path, $key->path);
     284
     285            # if we affected more then one row something very bad has happened.
     286            unless ($rows == 1) {
     287                $query->finish;
     288                $log->logdie("affected row count is $rows instead of 1");
     289            }
     290
     291            $db->commit;
     292            $log->debug("commit");
     293        };
     294        if ($@) {
     295            $db->rollback;
     296            $log->debug("rollback");
     297            if ($@ =~ /Deadlock found/) {
     298                $log->warn("database deadlock retrying transaction: $@");
     299                redo TRANS;
     300            }
     301            $log->logdie("database error: $@");
     302        }
     303        last;
     304    }
    291305
    292306    $log->debug("leaving");
     
    330344    # key1.swap -> key2
    331345
    332     eval {
    333         {
    334             # key1 -> key1.swap
    335             my $query = $db->prepare_cached($sql->rename_object);
    336             # this SQL statment takes the new key name as the first param
    337             my $rows = $query->execute($key1->path . ".swap", $key1->path);
    338 
    339             # if we affected more then one row something very bad has happened.
    340             unless ($rows == 1) {
    341                 $query->finish;
    342                 $log->logdie("affected row count is $rows instead of 1");
    343             }
    344         }
    345 
    346         {
    347             # key2 -> key1
    348             my $query = $db->prepare_cached($sql->rename_object);
    349             # this SQL statment takes the new key name as the first param
    350             my $rows = $query->execute($key1->path, $key2->path);
    351 
    352             # if we affected more then one row something very bad has happened.
    353             unless ($rows == 1) {
    354                 $query->finish;
    355                 $log->logdie("affected row count is $rows instead of 1");
    356             }
    357         }
    358 
    359         {
    360             # key1.swap -> key2
    361             my $query = $db->prepare_cached($sql->rename_object);
    362             # this SQL statment takes the new key name as the first param
    363             my $rows = $query->execute($key2->path, $key1->path . ".swap");
    364 
    365             # if we affected more then one row something very bad has happened.
    366             unless ($rows == 1) {
    367                 $query->finish;
    368                 $log->logdie("affected row count is $rows instead of 1");
    369             }
    370         }
    371 
    372         $db->commit;
    373         $log->debug("commit");
    374     };
    375     if ($@) {
    376         $db->rollback;
    377         $log->debug("rollback");
    378         $log->logdie("database error: $@");
     346TRANS: while (1) {
     347        eval {
     348            {
     349                # key1 -> key1.swap
     350                my $query = $db->prepare_cached($sql->rename_object);
     351                # this SQL statment takes the new key name as the first param
     352                my $rows = $query->execute($key1->path . ".swap", $key1->path);
     353
     354                # if we affected more then one row something very bad has happened.
     355                unless ($rows == 1) {
     356                    $query->finish;
     357                    $log->logdie("affected row count is $rows instead of 1");
     358                }
     359            }
     360
     361            {
     362                # key2 -> key1
     363                my $query = $db->prepare_cached($sql->rename_object);
     364                # this SQL statment takes the new key name as the first param
     365                my $rows = $query->execute($key1->path, $key2->path);
     366
     367                # if we affected more then one row something very bad has happened.
     368                unless ($rows == 1) {
     369                    $query->finish;
     370                    $log->logdie("affected row count is $rows instead of 1");
     371                }
     372            }
     373
     374            {
     375                # key1.swap -> key2
     376                my $query = $db->prepare_cached($sql->rename_object);
     377                # this SQL statment takes the new key name as the first param
     378                my $rows = $query->execute($key2->path, $key1->path . ".swap");
     379
     380                # if we affected more then one row something very bad has happened.
     381                unless ($rows == 1) {
     382                    $query->finish;
     383                    $log->logdie("affected row count is $rows instead of 1");
     384                }
     385            }
     386
     387            $db->commit;
     388            $log->debug("commit");
     389        };
     390        if ($@) {
     391            $db->rollback;
     392            $log->debug("rollback");
     393            if ($@ =~ /Deadlock found/) {
     394                $log->warn("database deadlock retrying transaction: $@");
     395                redo TRANS;
     396            }
     397            $log->logdie("database error: $@");
     398        }
     399        last;
    379400    }
    380401
     
    448469
    449470    my $uri;
    450     eval {
    451         my $so_id;
    452         {
    453             # verify that at least one instance is currently available
    454             my $query = $db->prepare_cached( $sql->get_object_instances );
    455             my $rows = $query->execute($key->path, 1);
    456 
    457             unless ( $rows > 0 ) {
     471TRANS: while (1) {
     472        eval {
     473            my $so_id;
     474            {
     475                # verify that at least one instance is currently available
     476                my $query = $db->prepare_cached( $sql->get_object_instances );
     477                my $rows = $query->execute($key->path, 1);
     478
     479                unless ( $rows > 0 ) {
     480                    $query->finish;
     481                    $log->logdie( "storage object does not exist" );
     482                }
     483
     484                $so_id = $query->fetchrow_hashref->{ 'so_id' };
    458485                $query->finish;
    459                 $log->logdie( "storage object does not exist" );
    460             }
    461 
    462             $so_id = $query->fetchrow_hashref->{ 'so_id' };
    463             $query->finish;
    464         }
    465 
    466         {
    467             my $query = $db->prepare_cached( $sql->new_instance );
    468             $query->execute($so_id, $vol_id);
    469         }
    470 
    471         my $ins_id;
    472         {
    473             my $query = $db->prepare_cached( $sql->last_insert_id );
    474             $query->execute();
    475             ($ins_id) = $query->fetchrow_array;
    476             # XXX finish seems to be required when using LAST_INSERT_ID() or we
    477             # get a warning about the stmt handling still being active the next
    478             # time LAST_INSERT_ID() is invoked
    479             $query->finish;
    480         }
    481 
    482         # Unfortunately, since we want to use the instance row's ID as part of
    483         # the actual on disk file name we can't try to create the file until
    484         # after we've create both a new storage_storage object and instance.
    485 
    486         # TODO add some stuff here to retry if unsucessful
    487         $uri = $self->_create_empty_instance_file($key->path, $so_id, $ins_id, $vol_path, $vol_xattr);
    488 
    489         {
    490             my $query = $db->prepare_cached( $sql->update_instance_uri );
    491             # vol_id, uri, ins_id
    492             $query->execute($vol_id, $uri, $ins_id);
    493         }
    494 
    495         $db->commit;
    496         $log->debug("commit");
    497     };
    498     if ($@) {
    499         $db->rollback;
    500         # handle soft volumes
    501         if (defined $vol_name and defined $key->soft_volume) {
    502             $log->debug("retrying with 'any' volume");
    503             return $self->replicate_object($key->path, 'any');
    504         }
    505         $log->debug("rollback");
    506         $log->logdie("error: $@");
     486            }
     487
     488            {
     489                my $query = $db->prepare_cached( $sql->new_instance );
     490                $query->execute($so_id, $vol_id);
     491            }
     492
     493            my $ins_id;
     494            {
     495                my $query = $db->prepare_cached( $sql->last_insert_id );
     496                $query->execute();
     497                ($ins_id) = $query->fetchrow_array;
     498                # XXX finish seems to be required when using LAST_INSERT_ID() or we
     499                # get a warning about the stmt handling still being active the next
     500                # time LAST_INSERT_ID() is invoked
     501                $query->finish;
     502            }
     503
     504            # Unfortunately, since we want to use the instance row's ID as part of
     505            # the actual on disk file name we can't try to create the file until
     506            # after we've create both a new storage_storage object and instance.
     507
     508            # TODO add some stuff here to retry if unsucessful
     509            $uri = $self->_create_empty_instance_file($key->path, $so_id, $ins_id, $vol_path, $vol_xattr);
     510
     511            {
     512                my $query = $db->prepare_cached( $sql->update_instance_uri );
     513                # vol_id, uri, ins_id
     514                $query->execute($vol_id, $uri, $ins_id);
     515            }
     516
     517            $db->commit;
     518            $log->debug("commit");
     519        };
     520        if ($@) {
     521            $db->rollback;
     522            # handle soft volumes
     523            if (defined $vol_name and defined $key->soft_volume) {
     524                $log->debug("retrying with 'any' volume");
     525                return $self->replicate_object($key->path, 'any');
     526            }
     527            $log->debug("rollback");
     528            if ($@ =~ /Deadlock found/) {
     529                $log->warn("database deadlock retrying transaction: $@");
     530                redo TRANS;
     531            }
     532            $log->logdie("error: $@");
     533        }
     534        last;
    507535    }
    508536
     
    545573    my $write_lock;
    546574
    547     eval {
    548         {
    549             # this will set update locks
    550             my $query = $db->prepare_cached( $sql->get_object_locks );
    551             my $rows = $query->execute( $key->path );
    552             unless ( $rows == 1 ) {
     575TRANS: while (1) {
     576        eval {
     577            {
     578                # this will set update locks
     579                my $query = $db->prepare_cached( $sql->get_object_locks );
     580                my $rows = $query->execute( $key->path );
     581                unless ( $rows == 1 ) {
     582                    $query->finish;
     583                    $log->logdie( "storage object does not exist" );
     584                }
     585
     586                my $row = $query->fetchrow_hashref;
    553587                $query->finish;
    554                 $log->logdie( "storage object does not exist" );
    555             }
    556 
    557             my $row = $query->fetchrow_hashref;
    558             $query->finish;
    559 
    560             $so_id      = $row->{ 'so_id' };
    561             $read_lock  = $row->{ 'read_lock' };
    562             $write_lock = $row->{ 'write_lock' };
    563         }
    564 
    565         if ($type eq 'write') {
    566             # can't set a write lock twice and
    567             # can't set a write lock if there are read locks
    568             if ($write_lock) {
    569                 $log->logdie("can not write lock twice -- retry");
    570             }
    571            
    572             if ($read_lock > 0) {
    573                 $log->logdie("can not write lock after read lock -- retry");
    574             }
    575 
    576             {
    577                 my $query = $db->prepare_cached( $sql->set_write_lock );
    578                 my $rows = $query->execute($key->path);
    579            
    580                 # if we affected more then one row something very bad has happened.
    581                 unless ($rows == 1) {
    582                     $log->logdie("affected row count is $rows instead of 1");
    583                 }
    584 
    585             }
    586         } elsif ($type eq 'read') {
    587             # can't set a read lock if there's a write lock
    588             if ($write_lock) {
    589                 $log->logdie("can not read lock after write lock -- retry");
    590             }
    591 
    592             {
    593                 my $query = $db->prepare_cached( $sql->increment_read_lock );
    594                 my $rows = $query->execute($key->path);
    595            
    596                 # if we affected more then one row something very bad has happened.
    597                 unless ($rows == 1) {
    598                     $log->logdie("affected row count is $rows instead of 1");
    599                 }
    600             }
    601         }
    602 
    603         $db->commit;
    604         $log->debug("commit");
    605     };
    606     if ($@) {
    607         $db->rollback;
    608         $log->debug("rollback");
    609         $log->logdie("error: $@");
     588
     589                $so_id      = $row->{ 'so_id' };
     590                $read_lock  = $row->{ 'read_lock' };
     591                $write_lock = $row->{ 'write_lock' };
     592            }
     593
     594            if ($type eq 'write') {
     595                # can't set a write lock twice and
     596                # can't set a write lock if there are read locks
     597                if ($write_lock) {
     598                    $log->logdie("can not write lock twice -- retry");
     599                }
     600               
     601                if ($read_lock > 0) {
     602                    $log->logdie("can not write lock after read lock -- retry");
     603                }
     604
     605                {
     606                    my $query = $db->prepare_cached( $sql->set_write_lock );
     607                    my $rows = $query->execute($key->path);
     608               
     609                    # if we affected more then one row something very bad has happened.
     610                    unless ($rows == 1) {
     611                        $log->logdie("affected row count is $rows instead of 1");
     612                    }
     613
     614                }
     615            } elsif ($type eq 'read') {
     616                # can't set a read lock if there's a write lock
     617                if ($write_lock) {
     618                    $log->logdie("can not read lock after write lock -- retry");
     619                }
     620
     621                {
     622                    my $query = $db->prepare_cached( $sql->increment_read_lock );
     623                    my $rows = $query->execute($key->path);
     624               
     625                    # if we affected more then one row something very bad has happened.
     626                    unless ($rows == 1) {
     627                        $log->logdie("affected row count is $rows instead of 1");
     628                    }
     629                }
     630            }
     631
     632            $db->commit;
     633            $log->debug("commit");
     634        };
     635        if ($@) {
     636            $db->rollback;
     637            $log->debug("rollback");
     638            if ($@ =~ /Deadlock found/) {
     639                $log->warn("database deadlock retrying transaction: $@");
     640                redo TRANS;
     641            }
     642            $log->logdie("error: $@");
     643        }
     644        last;
    610645    }
    611646
     
    648683    my $write_lock;
    649684
    650     eval {
    651         {
    652             # this will set update locks
    653             my $query = $db->prepare_cached( $sql->get_object_locks );
    654             my $rows = $query->execute($key->path);
    655             unless ($rows == 1) {
     685TRANS: while (1) {
     686        eval {
     687            {
     688                # this will set update locks
     689                my $query = $db->prepare_cached( $sql->get_object_locks );
     690                my $rows = $query->execute($key->path);
     691                unless ($rows == 1) {
     692                    $query->finish;
     693                    $log->logdie("storage object does not exist");
     694                }
     695
     696                my $row = $query->fetchrow_hashref;
    656697                $query->finish;
    657                 $log->logdie("storage object does not exist");
    658             }
    659 
    660             my $row = $query->fetchrow_hashref;
    661             $query->finish;
    662 
    663             $so_id      = $row->{ 'so_id' };
    664             $read_lock  = $row->{ 'read_lock' };
    665             $write_lock = $row->{ 'write_lock' };
    666         }
    667 
    668         if ($type eq 'write') {
    669             # can't remove a write lock if it doesn't exist
    670             if ($read_lock) {
    671                 $log->logdie("can not have a write lock under a read lock");
    672             }
    673 
    674             unless ($write_lock) {
    675                 $log->logdie("can not remove non-existant write lock");
    676             }
    677 
    678             {
    679                 my $query = $db->prepare_cached( $sql->delete_write_lock );
    680                 my $rows = $query->execute($key->path);
    681            
    682                 # if we affected more then one row something very bad has happened.
    683                 unless ($rows == 1) {
    684                     $log->logdie("affected row count is $rows instead of 1");
    685                 }
    686             }
    687         } elsif ($type eq 'read') {
    688             # can't remove a read lock if there's a write lock and
    689             # can't remove a read lock if there aren't any
    690             if ($write_lock) {
    691                 $log->logdie("can not have a read lock under a write lock");
    692             }
    693                
    694             if ($read_lock == 0) {
    695                 $log->logdie("can not remove non-existant read lock");
    696             }
    697 
    698             {
    699                 my $query = $db->prepare_cached( $sql->decrement_read_lock );
    700                 my $rows = $query->execute($key->path);
    701            
    702                 # if we affected more then one row something very bad has happened.
    703                 unless ($rows == 1) {
    704                     $log->logdie("affected row count is $rows instead of 1");
    705                 }
    706 
    707             }
    708         }
    709         $db->commit;
    710         $log->debug("commit");
    711     };
    712     if ($@) {
    713         $db->rollback;
    714         $log->debug("rollback");
    715         $log->logdie("error: $@");
     698
     699                $so_id      = $row->{ 'so_id' };
     700                $read_lock  = $row->{ 'read_lock' };
     701                $write_lock = $row->{ 'write_lock' };
     702            }
     703
     704            if ($type eq 'write') {
     705                # can't remove a write lock if it doesn't exist
     706                if ($read_lock) {
     707                    $log->logdie("can not have a write lock under a read lock");
     708                }
     709
     710                unless ($write_lock) {
     711                    $log->logdie("can not remove non-existant write lock");
     712                }
     713
     714                {
     715                    my $query = $db->prepare_cached( $sql->delete_write_lock );
     716                    my $rows = $query->execute($key->path);
     717               
     718                    # if we affected more then one row something very bad has happened.
     719                    unless ($rows == 1) {
     720                        $log->logdie("affected row count is $rows instead of 1");
     721                    }
     722                }
     723            } elsif ($type eq 'read') {
     724                # can't remove a read lock if there's a write lock and
     725                # can't remove a read lock if there aren't any
     726                if ($write_lock) {
     727                    $log->logdie("can not have a read lock under a write lock");
     728                }
     729                   
     730                if ($read_lock == 0) {
     731                    $log->logdie("can not remove non-existant read lock");
     732                }
     733
     734                {
     735                    my $query = $db->prepare_cached( $sql->decrement_read_lock );
     736                    my $rows = $query->execute($key->path);
     737               
     738                    # if we affected more then one row something very bad has happened.
     739                    unless ($rows == 1) {
     740                        $log->logdie("affected row count is $rows instead of 1");
     741                    }
     742
     743                }
     744            }
     745            $db->commit;
     746            $log->debug("commit");
     747        };
     748        if ($@) {
     749            $db->rollback;
     750            $log->debug("rollback");
     751            if ($@ =~ /Deadlock found/) {
     752                $log->warn("database deadlock retrying transaction: $@");
     753                redo TRANS;
     754            }
     755            $log->logdie("error: $@");
     756        }
     757        last;
    716758    }
    717759
     
    756798    $key = parse_neb_key($key);
    757799
    758     eval {
    759         my $query;
    760 
    761         if ($flags eq 'create') {
    762             $query = $db->prepare_cached( $sql->new_object_xattr );
    763         } else {
    764             # replace
    765             $query = $db->prepare_cached( $sql->replace_object_xattr );
    766         }
    767 
    768         # name, value, ext_id
    769         my $rows = $query->execute($name, $value, $key->path);
    770         $query->finish;
    771 
    772         # if we affected more then one row something very bad has happened.
    773         if ($flags eq 'create') {
    774             unless ($rows == 1) {
    775                 $log->logdie( "affected row count is $rows instead of 1" );
    776             }
    777         } else {
    778             # replace_object_xattr can effect either 1 or 2 rows.  2 rows in
    779             # the case of a replace and 1 if the xattr didn't already exist.
    780             unless ($rows == 1 or $rows == 2) {
    781                 $log->logdie( "affected row count is $rows instead of 2" );
    782             }
    783         }
    784 
    785         $db->commit;
    786         $log->debug("commit");
    787     };
    788     if ($@) {
    789         $db->rollback;
    790         $log->debug("rollback");
    791         $log->logdie("database error: $@");
     800TRANS: while (1) {
     801        eval {
     802            my $query;
     803
     804            if ($flags eq 'create') {
     805                $query = $db->prepare_cached( $sql->new_object_xattr );
     806            } else {
     807                # replace
     808                $query = $db->prepare_cached( $sql->replace_object_xattr );
     809            }
     810
     811            # name, value, ext_id
     812            my $rows = $query->execute($name, $value, $key->path);
     813            $query->finish;
     814
     815            # if we affected more then one row something very bad has happened.
     816            if ($flags eq 'create') {
     817                unless ($rows == 1) {
     818                    $log->logdie( "affected row count is $rows instead of 1" );
     819                }
     820            } else {
     821                # replace_object_xattr can effect either 1 or 2 rows.  2 rows in
     822                # the case of a replace and 1 if the xattr didn't already exist.
     823                unless ($rows == 1 or $rows == 2) {
     824                    $log->logdie( "affected row count is $rows instead of 2" );
     825                }
     826            }
     827
     828            $db->commit;
     829            $log->debug("commit");
     830        };
     831        if ($@) {
     832            $db->rollback;
     833            $log->debug("rollback");
     834            if ($@ =~ /Deadlock found/) {
     835                $log->warn("database deadlock retrying transaction: $@");
     836                redo TRANS;
     837            }
     838            $log->logdie("database error: $@");
     839        }
     840        last;
    792841    }
    793842
     
    919968    $key = parse_neb_key($key);
    920969
    921     eval {
    922         my $query = $db->prepare_cached( $sql->remove_object_xattr );
    923         # ext_id, name
    924         my $rows = $query->execute($key->path, $name);
    925         $query->finish;
    926 
    927         # if we affected more then one row something very bad has happened.
    928         unless ($rows == 1) {
    929             $log->logdie( "affected row count is $rows instead of 1" );
    930         }
    931 
    932         $db->commit;
    933         $log->debug("commit");
    934     };
    935     if ($@) {
    936         $db->rollback;
    937         $log->debug("rollback");
    938         $log->logdie("database error: $@");
    939     }
     970TRANS: while (1) {
     971        eval {
     972            my $query = $db->prepare_cached( $sql->remove_object_xattr );
     973            # ext_id, name
     974            my $rows = $query->execute($key->path, $name);
     975            $query->finish;
     976
     977            # if we affected more then one row something very bad has happened.
     978            unless ($rows == 1) {
     979                $log->logdie( "affected row count is $rows instead of 1" );
     980            }
     981
     982            $db->commit;
     983            $log->debug("commit");
     984        };
     985        if ($@) {
     986            $db->rollback;
     987            $log->debug("rollback");
     988            if ($@ =~ /Deadlock found/) {
     989                $log->warn("database deadlock retrying transaction: $@");
     990                redo TRANS;
     991            }
     992            $log->logdie("database error: $@");
     993        }
     994        last;
     995    }
    940996
    941997    $log->debug("leaving");
     
    10991155    $log->debug( "entered - @_" );
    11001156
    1101     eval {
    1102         my $so_id;
    1103         my $instances;
    1104         # get so_id
    1105         {
    1106             my $query = $db->prepare_cached( $sql->get_object_from_uri );
    1107             my $rows = $query->execute( $uri );
    1108 
    1109             unless ( $rows > 0 ) {
     1157TRANS: while (1) {
     1158        eval {
     1159            my $so_id;
     1160            my $instances;
     1161            # get so_id
     1162            {
     1163                my $query = $db->prepare_cached( $sql->get_object_from_uri );
     1164                my $rows = $query->execute( $uri );
     1165
     1166                unless ( $rows > 0 ) {
     1167                    $query->finish;
     1168                    $log->logdie( "no instance is associated with uri" );
     1169                }
     1170
     1171                $so_id = $query->fetchrow_hashref->{ 'so_id' };
    11101172                $query->finish;
    1111                 $log->logdie( "no instance is associated with uri" );
    1112             }
    1113 
    1114             $so_id = $query->fetchrow_hashref->{ 'so_id' };
    1115             $query->finish;
    1116 
    1117         }
    1118 
    1119         {
    1120             my $query = $db->prepare_cached( $sql->get_instance_count );
    1121             $query->execute( $so_id );
    1122 
    1123             $instances = $query->fetchrow_hashref->{ 'count(ins_id)' };
    1124             $query->finish;
    1125         }
    1126 
    1127         # remove instance
    1128         {
    1129             my $query = $db->prepare_cached( $sql->delete_instance );
    1130             my $rows = $query->execute( $uri );
    1131             $query->finish;
    1132            
    1133             # if we affected something other then two rows something very bad
    1134             # has happened
    1135             unless ( $rows == 1 ) {
    1136                 $log->logdie( "affected row count is $rows instead of 1" );
    1137             }
    1138         }
    1139 
    1140         # if we just deleted the last instance associated with a storage object
    1141         # remove it too
    1142         if ( $instances == 1 ) {
    1143             # we just removed the last instance
    1144             my $query = $db->prepare_cached( $sql->delete_object );
    1145             my $rows = $query->execute( $so_id );
    1146             $query->finish;
    1147 
    1148             # TODO: this will have to be changed in order to support hardlinks
    1149             unless ( $rows == 1 ) {
    1150                 $log->logdie( "affected row count is $rows instead of 2" );
    1151             }
    1152         }
    1153 
    1154         $db->commit;
    1155         $log->debug("commit");
    1156     };
    1157     if ( $@ ) {
    1158         $db->rollback;
    1159         $log->debug("rollback");
    1160         $log->logdie( "database error: $@" );
     1173
     1174            }
     1175
     1176            {
     1177                my $query = $db->prepare_cached( $sql->get_instance_count );
     1178                $query->execute( $so_id );
     1179
     1180                $instances = $query->fetchrow_hashref->{ 'count(ins_id)' };
     1181                $query->finish;
     1182            }
     1183
     1184            # remove instance
     1185            {
     1186                my $query = $db->prepare_cached( $sql->delete_instance );
     1187                my $rows = $query->execute( $uri );
     1188                $query->finish;
     1189               
     1190                # if we affected something other then two rows something very bad
     1191                # has happened
     1192                unless ( $rows == 1 ) {
     1193                    $log->logdie( "affected row count is $rows instead of 1" );
     1194                }
     1195            }
     1196
     1197            # if we just deleted the last instance associated with a storage object
     1198            # remove it too
     1199            if ( $instances == 1 ) {
     1200                # we just removed the last instance
     1201                my $query = $db->prepare_cached( $sql->delete_object );
     1202                my $rows = $query->execute( $so_id );
     1203                $query->finish;
     1204
     1205                # TODO: this will have to be changed in order to support hardlinks
     1206                unless ( $rows == 1 ) {
     1207                    $log->logdie( "affected row count is $rows instead of 2" );
     1208                }
     1209            }
     1210
     1211            $db->commit;
     1212            $log->debug("commit");
     1213        };
     1214        if ( $@ ) {
     1215            $db->rollback;
     1216            $log->debug("rollback");
     1217            if ($@ =~ /Deadlock found/) {
     1218                $log->warn("database deadlock retrying transaction: $@");
     1219                redo TRANS;
     1220            }
     1221            $log->logdie( "database error: $@" );
     1222        }
     1223        last;
    11611224    }
    11621225
Note: See TracChangeset for help on using the changeset viewer.