IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Nov 30, 2009, 1:54:49 PM (17 years ago)
Author:
watersc1
Message:

Nebulous: Implemented a number of bug fixes and modifications to

ensure no loss of data.

  • Each volume can now be associated into a cabinet, defining their physical arrangement.
  • File creation: new files without a specified volume are created on a random volume from a subset of the N least full.
  • Replication: file replication uses the same volume selection method, with the constraints that a copy not be automatically placed on the same volume as another, and that the first copy not be housed within the same volume.
  • Cull: instead of removing the first available instance, first attempt to remove an instance on the same volume as another, then attempt to remove an instance in the same cabinet as another, and then remove the first only if those fail.
  • Corrected bug that prevented the deletion of an object if it had more than one unavailable instance.
  • Fixed nebdiskd to synchronize between volume->mountedvol tables and to properly remove volumes that were no longer accessible.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Nebulous-Server/lib/Nebulous/Server.pm

    r24995 r26292  
    3535use constant NFS_RETRY_WAIT     => 1;
    3636use constant TRANS_RETRY_WAIT   => 1;
     37
     38# This is the umask hack.
     39umask(0002);
     40
     41# This determines how many entries from the list of volumes sorted by free space are randomized.
     42my $topfew_count = 3;
    3743
    3844# transaction restart/retry regex
     
    905911            }
    906912
    907             # In MySQL you can't select from a table your deleting rows from so
     913            # In MySQL you can't select from a table you're deleting rows from so
    908914            # we first have to get a list of instances to be removed, and then
    909             # removed them.
     915            # remove them.
    910916            my $rows_found;
    911917            {
    912918                my $query = $db->prepare_cached( $sql->find_dead_instances_by_so_id );
    913919                $rows_found = $query->execute( $so_id );
    914                 foreach my $row ($query->fetchrow_hashref) {
     920                my $i = 0;
     921                while (my $row = $query->fetchrow_hashref) {
    915922                    # remove dead instances
     923#                   $log->warn("copied: $rows_copied found: $rows_found removed: $rows_removed");
    916924                    my $query = $db->prepare_cached( $sql->delete_instance_by_ins_id);
    917925                    $rows_removed += $query->execute( $row->{ins_id} );
     
    919927                $query->finish;
    920928            }
    921 
     929#           $log->warn("copied: $rows_copied found: $rows_found removed: $rows_removed");
    922930            # sanity check
    923931            die("instances inaccessible ($rows_copied) != instances removed ($rows_removed)")
     
    16921700}
    16931701
     1702sub find_instances_for_cull
     1703{
     1704    my $self = shift;
     1705
     1706    my $log = $self->log;
     1707    $log->debug("entered - @_");
     1708
     1709    my ($key, $vol_name) = validate_pos(@_,
     1710        {
     1711            type        => SCALAR,
     1712            callbacks   => {
     1713                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
     1714            },
     1715        },
     1716        {
     1717            type        => SCALAR|UNDEF,
     1718#            callbacks   => {
     1719#                # check that the volume name requested is valid
     1720#                'is valid volume name' => sub {
     1721#                    return 1 if not defined $_[0];
     1722#                    $self->_is_valid_volume_name($_[0])
     1723#                },
     1724#            },
     1725            optional    => 1,
     1726        },
     1727    );
     1728
     1729    my $sql = $self->sql;
     1730
     1731#    unless ($key) {
     1732#        $log->warn("key was undefined after validate_pos(), trying again...");
     1733#        return $self->find_instances(@_);
     1734#    }
     1735
     1736    # vol_name overrides the key implied volume
     1737    eval {
     1738        $key = parse_neb_key($key, $vol_name);
     1739    };
     1740    $log->logdie("$@") if $@;
     1741    $vol_name = $key->volume;
     1742
     1743    my $db  = $self->db($key);
     1744
     1745    # the key's volume can't be validiated on input for this method so we have
     1746    # to check it after parsing the key
     1747    if (defined $vol_name
     1748        and not $self->_is_valid_volume_name($key, $key->volume)) {
     1749        if ($key->hard_volume) {
     1750            $log->logdie("$vol_name is not a valid volume name");
     1751        } else {
     1752            $log->warn( "$vol_name is not a known volume name" );
     1753            $vol_name = undef;
     1754        }
     1755    }
     1756
     1757    my @locations;
     1758    eval {
     1759        my $query;
     1760        if ($vol_name) {
     1761            $query = $db->prepare_cached( $sql->get_object_instances_by_vol_name );
     1762            # ext_id, name, available
     1763            my $rows = $query->execute($key->path, $vol_name, 1);
     1764            unless ($rows > 0) {
     1765                $query->finish;
     1766                die("no instances on storage volume or volume is not avaiable for key: $key volume: $vol_name");
     1767            }
     1768        } else {
     1769            $query = $db->prepare_cached( $sql->get_object_instances );
     1770            # ext_id, available
     1771            my $rows = $query->execute($key->path, 1);
     1772            unless ($rows > 0) {
     1773                $query->finish;
     1774                die("no instances available for key: $key");
     1775            }
     1776        }
     1777       
     1778        while (my $row = $query->fetchrow_hashref) {
     1779#           my $instance_hash  = { uri => $row->{ 'uri' },
     1780#                                  vol_id => $row->{ 'vol_id' },
     1781#                                  cab_id => $row->{ 'cab_id'} };
     1782            my $instance = $row->{ 'uri' };
     1783            push @locations, $row if $instance;
     1784        }
     1785    };
     1786    if ($@) {
     1787        $db->rollback;
     1788        # handle soft volumes
     1789        if (defined $vol_name and not defined $key->hard_volume) {
     1790            $log->debug("retrying with 'any' volume");
     1791            return $self->find_instances($key->path, 'any');
     1792        }
     1793        $log->logdie("database error: $@");
     1794    }
     1795
     1796    # XXX remove this?
     1797    $log->logdie("no instances found") unless (scalar @locations);
     1798
     1799    $log->debug("found: @locations");
     1800
     1801    $log->debug("leaving");
     1802
     1803    return \@locations;
     1804}
     1805
    16941806
    16951807sub delete_instance
     
    19842096
    19852097    my ($key, $name, $hard_volume) = @_;
    1986 
     2098   
     2099#    $log->warn("_g_s_v: key:>$key< name:>$name< hard_vol:>$hard_volume<");
    19872100    my $sql = $self->sql;
    19882101    my $db  = $self->db($key);
     
    19962109            # %free, name, avaiable, allocate
    19972110            $rows = $query->execute(0.95, $name, 1, 1);
    1998             # XXX destinguish between non-existant and unaviable
     2111            # XXX destinguish between non-existant and unavailable
    19992112            unless ($rows > 0) {
    20002113                $query->finish;
     
    20162129            $query = $db->prepare_cached( $sql->get_storage_volume );
    20172130            # %free, avaiable, allocate
    2018             $rows = $query->execute(0.95, 1, 1);
     2131            $rows = $query->execute(0.95, 1, 1, $topfew_count);
    20192132            # there has to be atleast one storage volume
    20202133            unless ($rows > 0) {
     
    20622175    my $db  = $self->db($key);
    20632176
    2064     my ($vol_id, $vol_host, $vol_path, $xattr);
     2177    my ($vol_id, $vol_host, $vol_path, $xattr, $forbidden_cabinet);
    20652178    eval {
    20662179        my $rows;
    2067         my $query = $db->prepare_cached( $sql->get_replication_volume_for_ext_id );
     2180       
     2181        my $query = $db->prepare_cached( $sql->get_cabinets_for_ext_id );
     2182        $rows = $query->execute($key->path);
     2183        unless ($rows > 0) {
     2184            $query->finish;
     2185            die("Requested key $key does not exist");
     2186        }
     2187        if ($rows == 1) {
     2188            ($forbidden_cabinet) = $query->fetchrow_array;
     2189            unless (defined($forbidden_cabinet)) {
     2190                $forbidden_cabinet = 0;
     2191            }
     2192            $query->finish;
     2193        }
     2194        else {
     2195            $forbidden_cabinet = 0;
     2196            $query->finish;
     2197        }
     2198           
     2199
     2200        $query = $db->prepare_cached( $sql->get_replication_volume_for_ext_id );
    20682201        # ext_id, %free, avaiable, allocate
    2069         $rows = $query->execute($key->path, 0.95, 1, 1);
     2202        $rows = $query->execute($key->path, 0.95, 1, 1, $forbidden_cabinet, $topfew_count);
    20702203        # XXX destinguish between non-existant and unaviable
    20712204        unless ($rows > 0) {
     
    21752308
    21762309    # handle "any" volume
    2177     if ($vol_name eq 'any') {
     2310    if (($vol_name eq 'any')||($vol_name eq 'any.0')) {
    21782311        $log->debug( "found volume name $vol_name" );
    21792312        $log->debug( "leaving" );
     
    22002333    $log->debug( "leaving" );
    22012334
    2202     return;
     2335    return 0;
    22032336}
    22042337
Note: See TracChangeset for help on using the changeset viewer.