IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 24637


Ignore:
Timestamp:
Jul 1, 2009, 5:21:32 PM (17 years ago)
Author:
jhoblitt
Message:

add the ability to delete a storage object when it has instances that are offline

Location:
trunk/Nebulous-Server
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Nebulous-Server/Changes

    r24558 r24637  
    3131    - change Nebulous::Server->find_objects() to return dirs and to sort it's
    3232      output
     33    - add the ability to delete a storage object when it has instances that are
     34      offline
    3335     
    34360.16
  • trunk/Nebulous-Server/lib/Nebulous/Server.pm

    r24607 r24637  
    5656    my ($config) = @_;
    5757
    58     # log4perl is not avaliable until we call init()
     58    # log4perl is not available until we call init()
    5959    Nebulous::Server::Log->init($config);
    6060    my $log = Log::Log4perl::get_logger( "Nebulous::Server" );
     
    16221622TRANS: while (1) {
    16231623        eval {
    1624             my $instances;
     1624            my $total;
     1625            my $available;
    16251626            my $so_id;
    16261627            my $ins_id;
     
    16361637                my $record = $query->fetchrow_hashref;
    16371638                $so_id      = $record->{ 'so_id' };
    1638                 $instances  = $record->{ 'count(ins_id)' };
     1639                $total      = $record->{ 'total' };
     1640                $available  = $record->{ 'available' };
    16391641                $query->finish;
    16401642            }
     
    16641666                    die( "affected row count is $rows instead of 1" );
    16651667                }
    1666             }
    1667 
    1668             # if we just deleted the last instance associated with a storage object
    1669             # remove it too
    1670             if ( $instances == 1 ) {
     1668               
     1669            }
     1670
     1671            # if we just deleted the last 'available' instance associated with
     1672            # a storage object remove it too
     1673            if ( $available == 1 ) {
    16711674                # remove key from cache
    16721675                $self->cache->delete($key->path) if defined $self->cache;
    16731676
    1674                 # we just removed the last instance
     1677                # record the path of the innaccesible files for deferred
     1678                # deletion
     1679                {
     1680                    my $query = $db->prepare_cached( $sql->copy_instances_to_deleted );
     1681                    $query->execute( $so_id );
     1682                }
     1683                # remove all instances... not strictly nessicary as the delete
     1684                # from storage_object should cascade but the fkey was specified
     1685                # without the cascade
     1686                {
     1687                    my $query = $db->prepare_cached( $sql->delete_instance_by_so_id );
     1688                    $query->execute( $so_id );
     1689                }
     1690               
     1691                # delete the storage object, remaining instances should be
     1692                # removed via cascading delete
    16751693                my $query = $db->prepare_cached( $sql->delete_object );
    16761694                my $rows = $query->execute( $so_id );
  • trunk/Nebulous-Server/lib/Nebulous/Server/SQL.pm

    r24609 r24637  
    180180        WHERE ins_id = ?
    181181    },
     182    delete_instance_by_so_id => qq{
     183        DELETE FROM instance
     184        WHERE so_id = ?
     185    },
    182186    get_object_from_uri   => qq{
    183187        SELECT so_id
     
    198202    },
    199203    get_instance_count_by_ext_id   => qq{
    200         SELECT count(ins_id), so_id
     204        SELECT
     205            so_id,
     206            count(ins_id) as total,
     207            sum(available) as available
    201208        FROM instance
    202209        JOIN storage_object
    203210            USING(so_id)
     211        LEFT JOIN mountedvol
     212            USING(vol_id)
    204213        WHERE
    205214            ext_id = ?
    206215        GROUP BY so_id
     216    },
     217    copy_instances_to_deleted => qq{
     218        INSERT INTO deleted
     219        SELECT NULL, vol_id, uri
     220        FROM instance
     221        WHERE
     222            so_id = ?
    207223    },
    208224    get_object_instances    => qq{
     
    432448DROP TABLE IF EXISTS log;
    433449DROP TABLE IF EXISTS directory;
    434 DROP PROCEDURE IF EXISTS getmountedvol;
     450DROP TABLE IF EXISTS deleted;
    435451SET FOREIGN_KEY_CHECKS=1
    436452END
     453#DROP PROCEDURE IF EXISTS getmountedvol;
    437454    $sql{get_db_clear} = \@clear;
    438455}
     
    451468
    4524691;
     470
     471# ###
     472#
     473# CREATE PROCEDURE getmountedvol() DETERMINISTIC
     474# BEGIN
     475#     DECLARE done BOOLEAN DEFAULT FALSE;
     476#     DECLARE vol_idvar INT;
     477#     DECLARE namevar VARCHAR(255);
     478#     DECLARE hostvar VARCHAR(255);
     479#     DECLARE pathvar VARCHAR(255);
     480#     DECLARE allocatevar BOOLEAN;
     481#     DECLARE availablevar BOOLEAN;
     482#     DECLARE xattrvar BOOLEAN;
     483#     DECLARE trans_level VARCHAR(255);
     484#     DECLARE key_checks BOOLEAN;
     485#     DECLARE cur1 CURSOR FOR SELECT vol_id, name, host, path, allocate, available, xattr FROM myvolume;
     486#     DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = TRUE;
     487#
     488#     -- store the okey checking state
     489# --    SELECT @@FOREIGN_KEY_CHECKS INTO key_checks;
     490#     -- disable foregin check checks to prevent deadlocks on the mountedvol table
     491# --    SET FOREIGN_KEY_CHECKS=0;
     492#
     493#     -- make sure the temp table does not already exist... this can happy if the
     494#     -- stored proc fails for some reason
     495#     DROP TABLE IF EXISTS myvolume;
     496#     CREATE TEMPORARY TABLE myvolume LIKE volume;
     497#     INSERT INTO myvolume SELECT * FROM volume;
     498#
     499#     -- store the current transaction level
     500# --    SELECT @@session.tx_isolation INTO trans_level;
     501#     -- set trans level to repeatable-read so the volume table does not change
     502#     -- out from under our cursor
     503# --    SET @@session.tx_isolation = 'REPEATABLE-READ';
     504#
     505#     -- iterate over the volume table finding the coresponding entry in the
     506#     -- mount table and inserting union of the volume & mount row into the
     507#     -- mountedvol table
     508#     OPEN cur1;
     509#
     510#     myloop: LOOP
     511#         FETCH cur1 INTO vol_idvar, namevar, hostvar, pathvar, allocatevar, availablevar, xattrvar;
     512#         IF `done` THEN LEAVE myloop; END IF;
     513#         REPLACE INTO mountedvol
     514#             SELECT mountpoint, total, used, vol_idvar, namevar, hostvar, pathvar, allocatevar, availablevar, xattrvar
     515#             FROM
     516#                 (SELECT *, INSTR(pathvar, mountpoint) = 1 as substring
     517#                 FROM mount
     518#                 HAVING substring = 1
     519#                 ORDER BY substring DESC, LENGTH(mountpoint) DESC
     520#                 LIMIT 1) as bar;
     521#     END LOOP myloop;
     522#     
     523#     CLOSE cur1;
     524#
     525#     -- restore the original transaction level
     526# --    SET @@session.tx_isolation = trans_level;
     527#
     528#     -- restore the original key checking state
     529# --    SET @@FOREIGN_KEY_CHECKS = key_checks;
     530#
     531#     DROP TABLE IF EXISTS myvolume;
     532#
     533# --    SET FOREIGN_KEY_CHECKS=1;
     534#
     535#     COMMIT;
     536# END
    453537
    454538__DATA__
     
    568652    ins_id BIGINT NOT NULL AUTO_INCREMENT,
    569653    so_id BIGINT NOT NULL,
    570     FOREIGN KEY(so_id) REFERENCES storage_object(so_id),
     654    FOREIGN KEY(so_id) REFERENCES storage_object(so_id) ON DELETE CASCADE,
    571655    vol_id INT NOT NULL,
    572656    FOREIGN KEY(vol_id) REFERENCES volume(vol_id),
     
    593677###
    594678
    595 CREATE PROCEDURE getmountedvol() DETERMINISTIC
    596 BEGIN
    597     DECLARE done BOOLEAN DEFAULT FALSE;
    598     DECLARE vol_idvar INT;
    599     DECLARE namevar VARCHAR(255);
    600     DECLARE hostvar VARCHAR(255);
    601     DECLARE pathvar VARCHAR(255);
    602     DECLARE allocatevar BOOLEAN;
    603     DECLARE availablevar BOOLEAN;
    604     DECLARE xattrvar BOOLEAN;
    605     DECLARE trans_level VARCHAR(255);
    606     DECLARE key_checks BOOLEAN;
    607     DECLARE cur1 CURSOR FOR SELECT vol_id, name, host, path, allocate, available, xattr FROM myvolume;
    608     DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = TRUE;
    609 
    610     -- store the okey checking state
    611 --    SELECT @@FOREIGN_KEY_CHECKS INTO key_checks;
    612     -- disable foregin check checks to prevent deadlocks on the mountedvol table
    613 --    SET FOREIGN_KEY_CHECKS=0;
    614 
    615     -- make sure the temp table does not already exist... this can happy if the
    616     -- stored proc fails for some reason
    617     DROP TABLE IF EXISTS myvolume;
    618     CREATE TEMPORARY TABLE myvolume LIKE volume;
    619     INSERT INTO myvolume SELECT * FROM volume;
    620 
    621     -- store the current transaction level
    622 --    SELECT @@session.tx_isolation INTO trans_level;
    623     -- set trans level to repeatable-read so the volume table does not change
    624     -- out from under our cursor
    625 --    SET @@session.tx_isolation = 'REPEATABLE-READ';
    626 
    627     -- iterate over the volume table finding the coresponding entry in the
    628     -- mount table and inserting union of the volume & mount row into the
    629     -- mountedvol table
    630     OPEN cur1;
    631 
    632     myloop: LOOP
    633         FETCH cur1 INTO vol_idvar, namevar, hostvar, pathvar, allocatevar, availablevar, xattrvar;
    634         IF `done` THEN LEAVE myloop; END IF;
    635         REPLACE INTO mountedvol
    636             SELECT mountpoint, total, used, vol_idvar, namevar, hostvar, pathvar, allocatevar, availablevar, xattrvar
    637             FROM
    638                 (SELECT *, INSTR(pathvar, mountpoint) = 1 as substring
    639                 FROM mount
    640                 HAVING substring = 1
    641                 ORDER BY substring DESC, LENGTH(mountpoint) DESC
    642                 LIMIT 1) as bar;
    643     END LOOP myloop;
    644    
    645     CLOSE cur1;
    646 
    647     -- restore the original transaction level
    648 --    SET @@session.tx_isolation = trans_level;
    649 
    650     -- restore the original key checking state
    651 --    SET @@FOREIGN_KEY_CHECKS = key_checks;
    652 
    653     DROP TABLE IF EXISTS myvolume;
    654 
    655 --    SET FOREIGN_KEY_CHECKS=1;
    656 
    657     COMMIT;
    658 END
     679CREATE TABLE deleted (
     680    timestamp TIMESTAMP,
     681    vol_id INT NOT NULL,
     682    uri VARCHAR(255) NOT NULL,
     683    PRIMARY KEY(timestamp),
     684    KEY(vol_id),
     685    KEY(uri)
     686) ENGINE=innodb DEFAULT CHARSET=latin1;
  • trunk/Nebulous-Server/t/09_server_delete_instance.t

    r24356 r24637  
    88use warnings FATAL => qw( all );
    99
    10 use Test::More tests => 8;
     10use Test::More tests => 11;
    1111
    1212use lib qw( ./t ./lib );
     
    2020    dbpasswd    => $NEB_PASS,
    2121);
     22
     23use Test::DBUnit dsn => $NEB_DB, username => $NEB_USER, password => $NEB_PASS;
    2224
    2325Test::Nebulous->setup;
     
    4446
    4547    ok($neb->delete_instance($key, $uri2), "delete instance");
     48
     49    eval {
     50        $neb->find_instances($key);
     51    };
     52    like($@, qr/is valid object key/, "storage object was deleted");
     53}
     54
     55Test::Nebulous->setup;
     56
     57{
     58    my $key = "foo";
     59    my $uri1 = $neb->create_object($key, 'node01');
     60    my $uri2 = $neb->replicate_object($key, 'node2');
     61
     62    # make one of the instances unavailable
     63    my $dbh = test_dbh();
     64    $dbh->do("UPDATE mountedvol SET available = 0 WHERE name = 'node01'");
     65
     66    ok($neb->delete_instance($key, $uri2), "delete instance");
     67
     68    expected_dataset_ok(
     69        deleted => [vol_id => 1, uri => $uri1],
     70    );
    4671
    4772    eval {
Note: See TracChangeset for help on using the changeset viewer.