IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 23537


Ignore:
Timestamp:
Mar 25, 2009, 3:49:36 PM (17 years ago)
Author:
eugene
Message:

merge changes from trunk

Location:
branches/neb_distrib_20081210/Nebulous-Server
Files:
5 deleted
11 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/neb_distrib_20081210/Nebulous-Server

  • branches/neb_distrib_20081210/Nebulous-Server/Changes

    r20155 r23537  
    11Revision history for Nebulous
     2
     30.17
     4    - retry database transactions when a deadlock is detected
    25
    360.16
  • branches/neb_distrib_20081210/Nebulous-Server/MANIFEST

    r20989 r23537  
    1010bin/neb-voladd
    1111bin/nebdiskd
    12 docs/c_api.h
    1312docs/database_setup.txt
    1413docs/design.txt
     14docs/install.txt
    1515docs/requirements.txt
    16 docs/setup.txt
    17 docs/tmp.txt
    1816examples/Makefile
    1917examples/nebexample.c
  • branches/neb_distrib_20081210/Nebulous-Server/bin/neb-admin

    r20202 r23537  
    2323    $dbpass,
    2424    $dbuser,
     25    $so_id_start,
     26    $so_id_range,
    2527    $limit,
    2628    $pending,
     
    4143    'pendingreplicate|r'    => \$pending,
    4244    'pendingremoval'        => \$removal,
     45    'so_id_start=i'         => \$so_id_start,
     46    'so_id_range=i'         => \$so_id_range,
    4347    'limit|l=i'             => \$limit,
    4448    'verbose|v'             => \$verbose,
     
    5862
    5963# check to make sure that only one instance of neb-admin is running
     64# XXX this implies we should move pending replicate elsewhere
    6065my $pidfile = '/var/tmp/neb-admin';
    6166# abort if an instance is already running
     
    9196    $dbh->do("INSERT INTO myvolume SELECT * FROM volume");
    9297
     98    if (not defined $so_id_start) { $so_id_start = 0; }
     99    if (not defined $so_id_range) { $so_id_range = 100000; }
     100    my $so_id_end = $so_id_start + $so_id_range;
     101
     102    # XXX check if so_id_start is beyond MAX(so_id): if so, exit with exit status 10
     103    {
     104        my $query = $dbh->prepare("SELECT MAX(so_id) from storage_object");
     105        $query->execute;
     106        my $answer = $query->fetchrow_arrayref;
     107        my $max_so_id = $$answer[0];
     108        $query->finish;
     109
     110        if ($so_id_start > $max_so_id) {
     111            print STDERR "at end of so_id range, reset please\n";
     112            exit 10;
     113        }
     114    }
     115       
    93116    my $query = $dbh->prepare(
    94117    "        SELECT
     
    111134                USING(vol_id)
    112135            WHERE mymountedvol.available = 1
    113     --        WHERE storage_object_xattr.name = 'user.copies'
     136            AND storage_object_xattr.name = 'user.copies'
     137            AND storage_object.so_id >= $so_id_start
     138            AND storage_object.so_id <  $so_id_end
    114139            GROUP BY so_id
    115140            HAVING available_instances < instances OR instances < copies
  • branches/neb_distrib_20081210/Nebulous-Server/bin/neb-voladd

    r19797 r23537  
    7979=head1 SYNOPSIS
    8080
    81     neb-voladd --volume <volume name> --uri <volume uri>
     81    neb-voladd --vname <volume name> --vhost <host name> --uri <volume uri>
    8282    [--db <database>] [--user <username>] [--pass <password>] [--host <hostname]
    8383
     
    9292=over 4
    9393
    94 =item * --volume <volume name>
     94=item * --vname <volume name>
    9595
    9696Symbolic name of volume being added.
     97
     98=item * --vhost <host name>
     99
     100Name of the host that containes the C<URI> of the volume being added.
    97101
    98102=item * --uri|-u <volume uri>
  • branches/neb_distrib_20081210/Nebulous-Server/lib/Nebulous/Server.pm

    r20989 r23537  
    11# Copyright (c) 2004-2008  Joshua Hoblitt
    22#
    3 # $Id: Server.pm,v 1.93.6.1 2008-12-14 22:52:37 eugene Exp $
     3# $Id: Server.pm,v 1.96 2008-12-14 22:54:25 eugene Exp $
    44
    55package Nebulous::Server;
     
    176176
    177177    my $uri;
    178     eval {
    179         {
    180             # create storage_object
    181             my $query = $db->prepare_cached( $sql->new_object );
    182             $query->execute('NULL', $key->path);
    183         }
    184 
    185         my $so_id;
    186         {
    187             # get object ID
    188             my $query = $db->prepare_cached( $sql->last_insert_id );
    189             $query->execute;
    190             ($so_id) = $query->fetchrow_array;
    191             # XXX finish seems to be required when using LAST_INSERT_ID() or we
    192             # get a warning about the stmt handling still be active the next
    193             # time LAST_INSERT_ID() is invoked
    194             $query->finish;
    195         }
    196 
    197         {
    198             # create storage_object_attr
    199             my $query = $db->prepare_cached( $sql->new_object_attr );
    200             $query->execute($so_id);
    201         }
    202 
    203         {
    204            
    205             # create instance with no URI
     178TRANS: while (1) {
     179        eval {
     180            {
     181                # create storage_object
     182                my $query = $db->prepare_cached( $sql->new_object );
     183                $query->execute('NULL', $key->path);
     184            }
     185
     186            my $so_id;
     187            {
     188                # get object ID
     189                my $query = $db->prepare_cached( $sql->last_insert_id );
     190                $query->execute;
     191                ($so_id) = $query->fetchrow_array;
     192                # XXX finish seems to be required when using LAST_INSERT_ID() or we
     193                # get a warning about the stmt handling still be active the next
     194                # time LAST_INSERT_ID() is invoked
     195                $query->finish;
     196            }
     197
     198            {
     199                # create storage_object_attr
     200                my $query = $db->prepare_cached( $sql->new_object_attr );
     201                $query->execute($so_id);
     202            }
     203
     204            {
     205               
     206                # create instance with no URI
    206207#            my $query = $db->prepare_cached( $sql->new_instance );
    207             my $query = $db->prepare_cached( $sql->new_object_instance );
    208             $query->execute($vol_id);
    209         }
    210 
    211         my $ins_id;
    212         {
    213             # get instance ID
    214             my $query = $db->prepare_cached( $sql->last_insert_id );
    215             $query->execute;
    216             ($ins_id) = $query->fetchrow_array;
    217             # XXX finish seems to be required when using LAST_INSERT_ID() or we
    218             # get a warning about the stmt handling still be active the next
    219             # time LAST_INSERT_ID() is invoked
    220             $query->finish;
    221         }
    222 
    223         # Unfortunately, since we want to use the instance row's ID as part of the
    224         # actual on disk file name we can't try to create the file until after
    225         # we've create both a new storage_storage object and instance.
    226 
    227         # TODO add some stuff here to retry if unsucessful
    228         $uri = $self->_create_empty_instance_file($key->path, $so_id, $ins_id, $vol_path, $vol_xattr);
    229         $log->debug("created $uri on volume ID: $vol_id");
    230 
    231         {
    232             # update the instance with URI & vol_id that the file is on
    233             my $query = $db->prepare_cached( $sql->update_instance_uri );
    234             # vol_id, uri, ins_id
    235             $query->execute($vol_id, "$uri", $ins_id);
    236         }
    237 
    238         $db->commit;
    239         $log->debug("commit");
    240     };
    241     if ($@) {
     208                my $query = $db->prepare_cached( $sql->new_object_instance );
     209                $query->execute($vol_id);
     210            }
     211
     212            my $ins_id;
     213            {
     214                # get instance ID
     215                my $query = $db->prepare_cached( $sql->last_insert_id );
     216                $query->execute;
     217                ($ins_id) = $query->fetchrow_array;
     218                # XXX finish seems to be required when using LAST_INSERT_ID() or we
     219                # get a warning about the stmt handling still be active the next
     220                # time LAST_INSERT_ID() is invoked
     221                $query->finish;
     222            }
     223
     224            # Unfortunately, since we want to use the instance row's ID as part of the
     225            # actual on disk file name we can't try to create the file until after
     226            # we've create both a new storage_storage object and instance.
     227
     228            # TODO add some stuff here to retry if unsucessful
     229            $uri = $self->_create_empty_instance_file($key->path, $so_id, $ins_id, $vol_path, $vol_xattr);
     230            $log->debug("created $uri on volume ID: $vol_id");
     231
     232            {
     233                # update the instance with URI & vol_id that the file is on
     234                my $query = $db->prepare_cached( $sql->update_instance_uri );
     235                # vol_id, uri, ins_id
     236                $query->execute($vol_id, "$uri", $ins_id);
     237            }
     238
     239            $db->commit;
     240            $log->debug("commit");
     241        };
     242        if ($@) {
    242243#        and not $key->soft_volume
    243         $db->rollback;
    244         $log->debug("rollback");
    245         $log->logdie("error: $@");
     244            $db->rollback;
     245            $log->debug("rollback");
     246            if ($@ =~ /Deadlock found/) {
     247                $log->warn("database deadlock retrying transaction: $@");
     248                redo TRANS;
     249            }
     250            $log->logdie("error: $@");
     251        }
     252        last;
    246253    }
    247254
     
    282289    $newkey = parse_neb_key($newkey);
    283290
    284     eval {
    285         # rename storage_object
    286         my $query = $db->prepare_cached($sql->rename_object);
    287         # this SQL statment takes the new key name as the first param
    288         my $rows = $query->execute($newkey->path, $key->path);
    289 
    290         # if we affected more then one row something very bad has happened.
    291         unless ($rows == 1) {
    292             $query->finish;
    293             $log->logdie("affected row count is $rows instead of 1");
    294         }
    295 
    296         $db->commit;
    297         $log->debug("commit");
    298     };
    299     if ($@) {
    300         $db->rollback;
    301         $log->debug("rollback");
    302         $log->logdie("database error: $@");
    303     }
     291TRANS: while (1) {
     292        eval {
     293            # rename storage_object
     294            my $query = $db->prepare_cached($sql->rename_object);
     295            # this SQL statment takes the new key name as the first param
     296            my $rows = $query->execute($newkey->path, $key->path);
     297
     298            # if we affected more then one row something very bad has happened.
     299            unless ($rows == 1) {
     300                $query->finish;
     301                $log->logdie("affected row count is $rows instead of 1");
     302            }
     303
     304            $db->commit;
     305            $log->debug("commit");
     306        };
     307        if ($@) {
     308            $db->rollback;
     309            $log->debug("rollback");
     310            if ($@ =~ /Deadlock found/) {
     311                $log->warn("database deadlock retrying transaction: $@");
     312                redo TRANS;
     313            }
     314            $log->logdie("database error: $@");
     315        }
     316        last;
     317    }
    304318
    305319    $log->debug("leaving");
     
    462476#     return 1;
    463477# }
    464 
     478#
     479
     480# ### this block below comes from the single branch, and implements
     481#      the transactions in the new way (two passes?).  the above handles
     482#      the case of multiple dbs
     483#
     484# TRANS: while (1) {
     485#         eval {
     486#             {
     487#                 # key1 -> key1.swap
     488#                 my $query = $db->prepare_cached($sql->rename_object);
     489#                 # this SQL statment takes the new key name as the first param
     490#                 my $rows = $query->execute($key1->path . ".swap", $key1->path);
     491#
     492#                 # if we affected more then one row something very bad has happened.
     493#                 unless ($rows == 1) {
     494#                     $query->finish;
     495#                     $log->logdie("affected row count is $rows instead of 1");
     496#                 }
     497#             }
     498#
     499#             {
     500#                 # key2 -> key1
     501#                 my $query = $db->prepare_cached($sql->rename_object);
     502#                 # this SQL statment takes the new key name as the first param
     503#                 my $rows = $query->execute($key1->path, $key2->path);
     504#
     505#                 # if we affected more then one row something very bad has happened.
     506#                 unless ($rows == 1) {
     507#                     $query->finish;
     508#                     $log->logdie("affected row count is $rows instead of 1");
     509#                 }
     510#             }
     511#
     512#             {
     513#                 # key1.swap -> key2
     514#                 my $query = $db->prepare_cached($sql->rename_object);
     515#                 # this SQL statment takes the new key name as the first param
     516#                 my $rows = $query->execute($key2->path, $key1->path . ".swap");
     517#
     518#                 # if we affected more then one row something very bad has happened.
     519#                 unless ($rows == 1) {
     520#                     $query->finish;
     521#                     $log->logdie("affected row count is $rows instead of 1");
     522#                 }
     523#             }
     524#
     525#             $db->commit;
     526#             $log->debug("commit");
     527#         };
     528#         if ($@) {
     529#             $db->rollback;
     530#             $log->debug("rollback");
     531#             if ($@ =~ /Deadlock found/) {
     532#                 $log->warn("database deadlock retrying transaction: $@");
     533#                 redo TRANS;
     534#             }
     535#             $log->logdie("database error: $@");
     536#         }
     537#         last;
     538#     }
     539#
     540#     $log->debug("leaving");
     541#
     542#     return 1;
     543# }
    465544
    466545sub replicate_object
     
    527606
    528607    my $uri;
    529     eval {
    530         my $so_id;
    531         {
    532             # verify that at least one instance is currently available
    533             my $query = $db->prepare_cached( $sql->get_object_instances );
    534             my $rows = $query->execute($key->path, 1);
    535 
    536             unless ( $rows > 0 ) {
     608TRANS: while (1) {
     609        eval {
     610            my $so_id;
     611            {
     612                # verify that at least one instance is currently available
     613                my $query = $db->prepare_cached( $sql->get_object_instances );
     614                my $rows = $query->execute($key->path, 1);
     615
     616                unless ( $rows > 0 ) {
     617                    $query->finish;
     618                    $log->logdie( "storage object does not exist" );
     619                }
     620
     621                $so_id = $query->fetchrow_hashref->{ 'so_id' };
    537622                $query->finish;
    538                 $log->logdie( "storage object does not exist" );
    539             }
    540 
    541             $so_id = $query->fetchrow_hashref->{ 'so_id' };
    542             $query->finish;
    543         }
    544 
    545         {
    546             my $query = $db->prepare_cached( $sql->new_instance );
    547             $query->execute($so_id, $vol_id);
    548         }
    549 
    550         my $ins_id;
    551         {
    552             my $query = $db->prepare_cached( $sql->last_insert_id );
    553             $query->execute();
    554             ($ins_id) = $query->fetchrow_array;
    555             # XXX finish seems to be required when using LAST_INSERT_ID() or we
    556             # get a warning about the stmt handling still being active the next
    557             # time LAST_INSERT_ID() is invoked
    558             $query->finish;
    559         }
    560 
    561         # Unfortunately, since we want to use the instance row's ID as part of
    562         # the actual on disk file name we can't try to create the file until
    563         # after we've create both a new storage_storage object and instance.
    564 
    565         # TODO add some stuff here to retry if unsucessful
    566         $uri = $self->_create_empty_instance_file($key->path, $so_id, $ins_id, $vol_path, $vol_xattr);
    567 
    568         {
    569             my $query = $db->prepare_cached( $sql->update_instance_uri );
    570             # vol_id, uri, ins_id
    571             $query->execute($vol_id, $uri, $ins_id);
    572         }
    573 
    574         $db->commit;
    575         $log->debug("commit");
    576     };
    577     if ($@) {
    578         $db->rollback;
    579         # handle soft volumes
    580         if (defined $vol_name and defined $key->soft_volume) {
    581             $log->debug("retrying with 'any' volume");
    582             return $self->replicate_object($key->path, 'any');
    583         }
    584         $log->debug("rollback");
    585         $log->logdie("error: $@");
     623            }
     624
     625            {
     626                my $query = $db->prepare_cached( $sql->new_instance );
     627                $query->execute($so_id, $vol_id);
     628            }
     629
     630            my $ins_id;
     631            {
     632                my $query = $db->prepare_cached( $sql->last_insert_id );
     633                $query->execute();
     634                ($ins_id) = $query->fetchrow_array;
     635                # XXX finish seems to be required when using LAST_INSERT_ID() or we
     636                # get a warning about the stmt handling still being active the next
     637                # time LAST_INSERT_ID() is invoked
     638                $query->finish;
     639            }
     640
     641            # Unfortunately, since we want to use the instance row's ID as part of
     642            # the actual on disk file name we can't try to create the file until
     643            # after we've create both a new storage_storage object and instance.
     644
     645            # TODO add some stuff here to retry if unsucessful
     646            $uri = $self->_create_empty_instance_file($key->path, $so_id, $ins_id, $vol_path, $vol_xattr);
     647
     648            {
     649                my $query = $db->prepare_cached( $sql->update_instance_uri );
     650                # vol_id, uri, ins_id
     651                $query->execute($vol_id, $uri, $ins_id);
     652            }
     653
     654            $db->commit;
     655            $log->debug("commit");
     656        };
     657        if ($@) {
     658            $db->rollback;
     659            # handle soft volumes
     660            if (defined $vol_name and defined $key->soft_volume) {
     661                $log->debug("retrying with 'any' volume");
     662                return $self->replicate_object($key->path, 'any');
     663            }
     664            $log->debug("rollback");
     665            if ($@ =~ /Deadlock found/) {
     666                $log->warn("database deadlock retrying transaction: $@");
     667                redo TRANS;
     668            }
     669            $log->logdie("error: $@");
     670        }
     671        last;
    586672    }
    587673
     
    624710    my $write_lock;
    625711
    626     eval {
    627         {
    628             # this will set update locks
    629             my $query = $db->prepare_cached( $sql->get_object_locks );
    630             my $rows = $query->execute( $key->path );
    631             unless ( $rows == 1 ) {
     712TRANS: while (1) {
     713        eval {
     714            {
     715                # this will set update locks
     716                my $query = $db->prepare_cached( $sql->get_object_locks );
     717                my $rows = $query->execute( $key->path );
     718                unless ( $rows == 1 ) {
     719                    $query->finish;
     720                    $log->logdie( "storage object does not exist" );
     721                }
     722
     723                my $row = $query->fetchrow_hashref;
    632724                $query->finish;
    633                 $log->logdie( "storage object does not exist" );
    634             }
    635 
    636             my $row = $query->fetchrow_hashref;
    637             $query->finish;
    638 
    639             $so_id      = $row->{ 'so_id' };
    640             $read_lock  = $row->{ 'read_lock' };
    641             $write_lock = $row->{ 'write_lock' };
    642         }
    643 
    644         if ($type eq 'write') {
    645             # can't set a write lock twice and
    646             # can't set a write lock if there are read locks
    647             if ($write_lock) {
    648                 $log->logdie("can not write lock twice -- retry");
    649             }
    650            
    651             if ($read_lock > 0) {
    652                 $log->logdie("can not write lock after read lock -- retry");
    653             }
    654 
    655             {
    656                 my $query = $db->prepare_cached( $sql->set_write_lock );
    657                 my $rows = $query->execute($key->path);
    658            
    659                 # if we affected more then one row something very bad has happened.
    660                 unless ($rows == 1) {
    661                     $log->logdie("affected row count is $rows instead of 1");
    662                 }
    663 
    664             }
    665         } elsif ($type eq 'read') {
    666             # can't set a read lock if there's a write lock
    667             if ($write_lock) {
    668                 $log->logdie("can not read lock after write lock -- retry");
    669             }
    670 
    671             {
    672                 my $query = $db->prepare_cached( $sql->increment_read_lock );
    673                 my $rows = $query->execute($key->path);
    674            
    675                 # if we affected more then one row something very bad has happened.
    676                 unless ($rows == 1) {
    677                     $log->logdie("affected row count is $rows instead of 1");
    678                 }
    679             }
    680         }
    681 
    682         $db->commit;
    683         $log->debug("commit");
    684     };
    685     if ($@) {
    686         $db->rollback;
    687         $log->debug("rollback");
    688         $log->logdie("error: $@");
     725
     726                $so_id      = $row->{ 'so_id' };
     727                $read_lock  = $row->{ 'read_lock' };
     728                $write_lock = $row->{ 'write_lock' };
     729            }
     730
     731            if ($type eq 'write') {
     732                # can't set a write lock twice and
     733                # can't set a write lock if there are read locks
     734                if ($write_lock) {
     735                    $log->logdie("can not write lock twice -- retry");
     736                }
     737               
     738                if ($read_lock > 0) {
     739                    $log->logdie("can not write lock after read lock -- retry");
     740                }
     741
     742                {
     743                    my $query = $db->prepare_cached( $sql->set_write_lock );
     744                    my $rows = $query->execute($key->path);
     745               
     746                    # if we affected more then one row something very bad has happened.
     747                    unless ($rows == 1) {
     748                        $log->logdie("affected row count is $rows instead of 1");
     749                    }
     750
     751                }
     752            } elsif ($type eq 'read') {
     753                # can't set a read lock if there's a write lock
     754                if ($write_lock) {
     755                    $log->logdie("can not read lock after write lock -- retry");
     756                }
     757
     758                {
     759                    my $query = $db->prepare_cached( $sql->increment_read_lock );
     760                    my $rows = $query->execute($key->path);
     761               
     762                    # if we affected more then one row something very bad has happened.
     763                    unless ($rows == 1) {
     764                        $log->logdie("affected row count is $rows instead of 1");
     765                    }
     766                }
     767            }
     768
     769            $db->commit;
     770            $log->debug("commit");
     771        };
     772        if ($@) {
     773            $db->rollback;
     774            $log->debug("rollback");
     775            if ($@ =~ /Deadlock found/) {
     776                $log->warn("database deadlock retrying transaction: $@");
     777                redo TRANS;
     778            }
     779            $log->logdie("error: $@");
     780        }
     781        last;
    689782    }
    690783
     
    727820    my $write_lock;
    728821
    729     eval {
    730         {
    731             # this will set update locks
    732             my $query = $db->prepare_cached( $sql->get_object_locks );
    733             my $rows = $query->execute($key->path);
    734             unless ($rows == 1) {
     822TRANS: while (1) {
     823        eval {
     824            {
     825                # this will set update locks
     826                my $query = $db->prepare_cached( $sql->get_object_locks );
     827                my $rows = $query->execute($key->path);
     828                unless ($rows == 1) {
     829                    $query->finish;
     830                    $log->logdie("storage object does not exist");
     831                }
     832
     833                my $row = $query->fetchrow_hashref;
    735834                $query->finish;
    736                 $log->logdie("storage object does not exist");
    737             }
    738 
    739             my $row = $query->fetchrow_hashref;
    740             $query->finish;
    741 
    742             $so_id      = $row->{ 'so_id' };
    743             $read_lock  = $row->{ 'read_lock' };
    744             $write_lock = $row->{ 'write_lock' };
    745         }
    746 
    747         if ($type eq 'write') {
    748             # can't remove a write lock if it doesn't exist
    749             if ($read_lock) {
    750                 $log->logdie("can not have a write lock under a read lock");
    751             }
    752 
    753             unless ($write_lock) {
    754                 $log->logdie("can not remove non-existant write lock");
    755             }
    756 
    757             {
    758                 my $query = $db->prepare_cached( $sql->delete_write_lock );
    759                 my $rows = $query->execute($key->path);
    760            
    761                 # if we affected more then one row something very bad has happened.
    762                 unless ($rows == 1) {
    763                     $log->logdie("affected row count is $rows instead of 1");
    764                 }
    765             }
    766         } elsif ($type eq 'read') {
    767             # can't remove a read lock if there's a write lock and
    768             # can't remove a read lock if there aren't any
    769             if ($write_lock) {
    770                 $log->logdie("can not have a read lock under a write lock");
    771             }
    772                
    773             if ($read_lock == 0) {
    774                 $log->logdie("can not remove non-existant read lock");
    775             }
    776 
    777             {
    778                 my $query = $db->prepare_cached( $sql->decrement_read_lock );
    779                 my $rows = $query->execute($key->path);
    780            
    781                 # if we affected more then one row something very bad has happened.
    782                 unless ($rows == 1) {
    783                     $log->logdie("affected row count is $rows instead of 1");
    784                 }
    785 
    786             }
    787         }
    788         $db->commit;
    789         $log->debug("commit");
    790     };
    791     if ($@) {
    792         $db->rollback;
    793         $log->debug("rollback");
    794         $log->logdie("error: $@");
     835
     836                $so_id      = $row->{ 'so_id' };
     837                $read_lock  = $row->{ 'read_lock' };
     838                $write_lock = $row->{ 'write_lock' };
     839            }
     840
     841            if ($type eq 'write') {
     842                # can't remove a write lock if it doesn't exist
     843                if ($read_lock) {
     844                    $log->logdie("can not have a write lock under a read lock");
     845                }
     846
     847                unless ($write_lock) {
     848                    $log->logdie("can not remove non-existant write lock");
     849                }
     850
     851                {
     852                    my $query = $db->prepare_cached( $sql->delete_write_lock );
     853                    my $rows = $query->execute($key->path);
     854               
     855                    # if we affected more then one row something very bad has happened.
     856                    unless ($rows == 1) {
     857                        $log->logdie("affected row count is $rows instead of 1");
     858                    }
     859                }
     860            } elsif ($type eq 'read') {
     861                # can't remove a read lock if there's a write lock and
     862                # can't remove a read lock if there aren't any
     863                if ($write_lock) {
     864                    $log->logdie("can not have a read lock under a write lock");
     865                }
     866                   
     867                if ($read_lock == 0) {
     868                    $log->logdie("can not remove non-existant read lock");
     869                }
     870
     871                {
     872                    my $query = $db->prepare_cached( $sql->decrement_read_lock );
     873                    my $rows = $query->execute($key->path);
     874               
     875                    # if we affected more then one row something very bad has happened.
     876                    unless ($rows == 1) {
     877                        $log->logdie("affected row count is $rows instead of 1");
     878                    }
     879
     880                }
     881            }
     882            $db->commit;
     883            $log->debug("commit");
     884        };
     885        if ($@) {
     886            $db->rollback;
     887            $log->debug("rollback");
     888            if ($@ =~ /Deadlock found/) {
     889                $log->warn("database deadlock retrying transaction: $@");
     890                redo TRANS;
     891            }
     892            $log->logdie("error: $@");
     893        }
     894        last;
    795895    }
    796896
     
    835935    $key = parse_neb_key($key);
    836936
    837     eval {
    838         my $query;
    839 
    840         if ($flags eq 'create') {
    841             $query = $db->prepare_cached( $sql->new_object_xattr );
    842         } else {
    843             # replace
    844             $query = $db->prepare_cached( $sql->replace_object_xattr );
    845         }
    846 
    847         # name, value, ext_id
    848         my $rows = $query->execute($name, $value, $key->path);
    849         $query->finish;
    850 
    851         # if we affected more then one row something very bad has happened.
    852         if ($flags eq 'create') {
    853             unless ($rows == 1) {
    854                 $log->logdie( "affected row count is $rows instead of 1" );
    855             }
    856         } else {
    857             # replace_object_xattr can effect either 1 or 2 rows.  2 rows in
    858             # the case of a replace and 1 if the xattr didn't already exist.
    859             unless ($rows == 1 or $rows == 2) {
    860                 $log->logdie( "affected row count is $rows instead of 2" );
    861             }
    862         }
    863 
    864         $db->commit;
    865         $log->debug("commit");
    866     };
    867     if ($@) {
    868         $db->rollback;
    869         $log->debug("rollback");
    870         $log->logdie("database error: $@");
     937TRANS: while (1) {
     938        eval {
     939            my $query;
     940
     941            if ($flags eq 'create') {
     942                $query = $db->prepare_cached( $sql->new_object_xattr );
     943            } else {
     944                # replace
     945                $query = $db->prepare_cached( $sql->replace_object_xattr );
     946            }
     947
     948            # name, value, ext_id
     949            my $rows = $query->execute($name, $value, $key->path);
     950            $query->finish;
     951
     952            # if we affected more then one row something very bad has happened.
     953            if ($flags eq 'create') {
     954                unless ($rows == 1) {
     955                    $log->logdie( "affected row count is $rows instead of 1" );
     956                }
     957            } else {
     958                # replace_object_xattr can effect either 1 or 2 rows.  2 rows in
     959                # the case of a replace and 1 if the xattr didn't already exist.
     960                unless ($rows == 1 or $rows == 2) {
     961                    $log->logdie( "affected row count is $rows instead of 2" );
     962                }
     963            }
     964
     965            $db->commit;
     966            $log->debug("commit");
     967        };
     968        if ($@) {
     969            $db->rollback;
     970            $log->debug("rollback");
     971            if ($@ =~ /Deadlock found/) {
     972                $log->warn("database deadlock retrying transaction: $@");
     973                redo TRANS;
     974            }
     975            $log->logdie("database error: $@");
     976        }
     977        last;
    871978    }
    872979
     
    9981105    $key = parse_neb_key($key);
    9991106
    1000     eval {
    1001         my $query = $db->prepare_cached( $sql->remove_object_xattr );
    1002         # ext_id, name
    1003         my $rows = $query->execute($key->path, $name);
    1004         $query->finish;
    1005 
    1006         # if we affected more then one row something very bad has happened.
    1007         unless ($rows == 1) {
    1008             $log->logdie( "affected row count is $rows instead of 1" );
    1009         }
    1010 
    1011         $db->commit;
    1012         $log->debug("commit");
    1013     };
    1014     if ($@) {
    1015         $db->rollback;
    1016         $log->debug("rollback");
    1017         $log->logdie("database error: $@");
    1018     }
     1107TRANS: while (1) {
     1108        eval {
     1109            my $query = $db->prepare_cached( $sql->remove_object_xattr );
     1110            # ext_id, name
     1111            my $rows = $query->execute($key->path, $name);
     1112            $query->finish;
     1113
     1114            # if we affected more then one row something very bad has happened.
     1115            unless ($rows == 1) {
     1116                $log->logdie( "affected row count is $rows instead of 1" );
     1117            }
     1118
     1119            $db->commit;
     1120            $log->debug("commit");
     1121        };
     1122        if ($@) {
     1123            $db->rollback;
     1124            $log->debug("rollback");
     1125            if ($@ =~ /Deadlock found/) {
     1126                $log->warn("database deadlock retrying transaction: $@");
     1127                redo TRANS;
     1128            }
     1129            $log->logdie("database error: $@");
     1130        }
     1131        last;
     1132    }
    10191133
    10201134    $log->debug("leaving");
     
    11861300    $log->debug( "entered - @_" );
    11871301
    1188     eval {
    1189         my $so_id;
    1190         my $instances;
    1191         # get so_id
    1192         {
    1193             my $query = $db->prepare_cached( $sql->get_object_from_uri );
    1194             my $rows = $query->execute( $uri );
    1195 
    1196             unless ( $rows > 0 ) {
     1302TRANS: while (1) {
     1303        eval {
     1304            my $so_id;
     1305            my $instances;
     1306            # get so_id
     1307            {
     1308                my $query = $db->prepare_cached( $sql->get_object_from_uri );
     1309                my $rows = $query->execute( $uri );
     1310
     1311                unless ( $rows > 0 ) {
     1312                    $query->finish;
     1313                    $log->logdie( "no instance is associated with uri" );
     1314                }
     1315
     1316                $so_id = $query->fetchrow_hashref->{ 'so_id' };
    11971317                $query->finish;
    1198                 $log->logdie( "no instance is associated with uri" );
    1199             }
    1200 
    1201             $so_id = $query->fetchrow_hashref->{ 'so_id' };
    1202             $query->finish;
    1203 
    1204         }
    1205 
    1206         {
    1207             my $query = $db->prepare_cached( $sql->get_instance_count );
    1208             $query->execute( $so_id );
    1209 
    1210             $instances = $query->fetchrow_hashref->{ 'count(ins_id)' };
    1211             $query->finish;
    1212         }
    1213 
    1214         # remove instance
    1215         {
    1216             my $query = $db->prepare_cached( $sql->delete_instance );
    1217             my $rows = $query->execute( $uri );
    1218             $query->finish;
    1219            
    1220             # if we affected something other then two rows something very bad
    1221             # has happened
    1222             unless ( $rows == 1 ) {
    1223                 $log->logdie( "affected row count is $rows instead of 1" );
    1224             }
    1225         }
    1226 
    1227         # if we just deleted the last instance associated with a storage object
    1228         # remove it too
    1229         if ( $instances == 1 ) {
    1230             # we just removed the last instance
    1231             my $query = $db->prepare_cached( $sql->delete_object );
    1232             my $rows = $query->execute( $so_id );
    1233             $query->finish;
    1234 
    1235             # TODO: this will have to be changed in order to support hardlinks
    1236             unless ( $rows == 1 ) {
    1237                 $log->logdie( "affected row count is $rows instead of 2" );
    1238             }
    1239         }
    1240 
    1241         $db->commit;
    1242         $log->debug("commit");
    1243     };
    1244     if ( $@ ) {
    1245         $db->rollback;
    1246         $log->debug("rollback");
    1247         $log->logdie( "database error: $@" );
     1318
     1319            }
     1320
     1321            {
     1322                my $query = $db->prepare_cached( $sql->get_instance_count );
     1323                $query->execute( $so_id );
     1324
     1325                $instances = $query->fetchrow_hashref->{ 'count(ins_id)' };
     1326                $query->finish;
     1327            }
     1328
     1329            # remove instance
     1330            {
     1331                my $query = $db->prepare_cached( $sql->delete_instance );
     1332                my $rows = $query->execute( $uri );
     1333                $query->finish;
     1334               
     1335                # if we affected something other then two rows something very bad
     1336                # has happened
     1337                unless ( $rows == 1 ) {
     1338                    $log->logdie( "affected row count is $rows instead of 1" );
     1339                }
     1340            }
     1341
     1342            # if we just deleted the last instance associated with a storage object
     1343            # remove it too
     1344            if ( $instances == 1 ) {
     1345                # we just removed the last instance
     1346                my $query = $db->prepare_cached( $sql->delete_object );
     1347                my $rows = $query->execute( $so_id );
     1348                $query->finish;
     1349
     1350                # TODO: this will have to be changed in order to support hardlinks
     1351                unless ( $rows == 1 ) {
     1352                    $log->logdie( "affected row count is $rows instead of 2" );
     1353                }
     1354            }
     1355
     1356            $db->commit;
     1357            $log->debug("commit");
     1358        };
     1359        if ( $@ ) {
     1360            $db->rollback;
     1361            $log->debug("rollback");
     1362            if ($@ =~ /Deadlock found/) {
     1363                $log->warn("database deadlock retrying transaction: $@");
     1364                redo TRANS;
     1365            }
     1366            $log->logdie( "database error: $@" );
     1367        }
     1368        last;
    12481369    }
    12491370
  • branches/neb_distrib_20081210/Nebulous-Server/lib/Nebulous/Server/Config.pm

    r20989 r23537  
    11# Copyright (C) 2005  Joshua Hoblitt
    22#
    3 # $Id: Config.pm,v 1.3.22.1 2008-12-14 22:52:37 eugene Exp $
     3# $Id: Config.pm,v 1.5 2008-12-14 22:54:25 eugene Exp $
    44
    55package Nebulous::Server::Config;
  • branches/neb_distrib_20081210/Nebulous-Server/lib/Nebulous/Server/Log.pm

    r20989 r23537  
    11# Copyright (c) 2004  Joshua Hoblitt
    22#
    3 # $Id: Log.pm,v 1.7.22.1 2008-12-14 22:52:37 eugene Exp $
     3# $Id: Log.pm,v 1.9 2008-12-14 22:54:25 eugene Exp $
    44
    55package Nebulous::Server::Log;
  • branches/neb_distrib_20081210/Nebulous-Server/lib/Nebulous/Server/SQL.pm

    r20989 r23537  
    11# Copyright (c) 2004  Joshua Hoblitt
    22#
    3 # $Id: SQL.pm,v 1.75.6.1 2008-12-14 22:52:37 eugene Exp $
     3# $Id: SQL.pm,v 1.78 2008-12-14 22:54:25 eugene Exp $
    44
    55package Nebulous::Server::SQL;
  • branches/neb_distrib_20081210/Nebulous-Server/t/02_server_setup.t

    r20989 r23537  
    33# Copryight (C) 2004-2005  Joshua Hoblitt
    44#
    5 # $Id: 02_server_setup.t,v 1.6.22.1 2008-12-14 22:52:37 eugene Exp $
     5# $Id: 02_server_setup.t,v 1.8 2008-12-14 22:54:25 eugene Exp $
    66
    77use strict;
  • branches/neb_distrib_20081210/Nebulous-Server/t/10_server_is_valid_volume_name.t

    r20989 r23537  
    33# Copryight (C) 2004-2005  Joshua Hoblitt
    44#
    5 # $Id: 10_server_is_valid_volume_name.t,v 1.5.22.1 2008-12-14 22:52:37 eugene Exp $
     5# $Id: 10_server_is_valid_volume_name.t,v 1.7 2008-12-14 22:54:25 eugene Exp $
    66
    77use strict;
Note: See TracChangeset for help on using the changeset viewer.