IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Apr 20, 2009, 11:15:20 AM (17 years ago)
Author:
jhoblitt
Message:

merge neb_distrib_20081210

Location:
trunk/Nebulous-Server
Files:
1 deleted
20 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/Nebulous-Server

  • trunk/Nebulous-Server/Build.PL

    r23675 r23932  
    2323        'File::Temp'            => 0,
    2424        'Filesys::Df'           => '0.92',
     25        'Log::Dispatch::Email::MailSend' => 0,
    2526        'Log::Log4perl'         => '0.48',
    26         'Log::Dispatch::Email::MailSend' => 0,
    2727        'Net::Server::Daemonize'=> '0.05',
    2828        'Params::Validate'      => '0.73',
     
    3434        'Test::More'            => '0.49',
    3535        'Test::URI'             => '1.06',
     36        'Test::DBUnit'          => '0.20',
    3637    },
    3738    recommends          => {
  • trunk/Nebulous-Server/Changes

    r23698 r23932  
    88    - add email logging of events to nebdiskd
    99    - attempt to optimize _is_valid_object_key() by eliminating an unused join
     10    - rename Nebulous::Keys class -> Nebulous::Key
     11    - select neb db to use by hashing only the directory component of the key
     12    - disallow Nebulous::Server->rename_object() when it would cause the db
     13      hash of a key to change
     14    - create a pseduo directory structure on key creation
     15    - Nebulous::Key parsing and testing improvements
     16    - change 'log_level' param to 'trace'
     17    - refactor ->find_objects() functionality
    1018     
    11190.16
  • trunk/Nebulous-Server/MANIFEST

    r23340 r23932  
    44MANIFEST
    55README
    6 Todo
    76bin/neb-admin
    87bin/neb-fsck
     
    1918examples/uri_test.pl
    2019init.d/nebdiskd
    21 lib/Nebulous/Keys.pm
     20lib/Nebulous/Key.pm
    2221lib/Nebulous/Server.pm
    2322lib/Nebulous/Server.pod
     
    3332t/00_distribution.t
    3433t/01_load.t
     34t/02_config.t
    3535t/02_server_setup.t
    3636t/03_server_create_object.t
  • trunk/Nebulous-Server/bin/neb-admin

    r23560 r23932  
    174174        # if the copies xattr is unset and the object has 2 or more instances, we
    175175        # will assume a target of 2 copies
     176       
     177        # XXX change this: there should be no default value or we will
     178        # have a race condition.  user.copies should never get set by
     179        # any client until AFTER a file is no longer in use.
    176180        my $copies = $obj->{copies} || 2;
    177181
  • trunk/Nebulous-Server/lib/Nebulous/Server.pm

    r23698 r23932  
    99no warnings qw( uninitialized );
    1010
    11 our $VERSION = '0.15';
     11our $VERSION = '0.17';
    1212
    1313use base qw( Class::Accessor::Fast );
     
    1515use DBI;
    1616use Digest::SHA1 qw( sha1_hex );
    17 use File::Basename qw( dirname );
     17use File::Basename qw( basename dirname fileparse );
    1818use File::ExtAttr qw( setfattr );
    1919use File::Path;
    2020use File::Spec;
    21 use Log::Log4perl;
    22 use Nebulous::Keys qw( parse_neb_key parse_neb_volume );
     21use Log::Log4perl qw( :levels );
     22use Nebulous::Key qw( parse_neb_key parse_neb_volume );
    2323use Nebulous::Server::Config;
    2424use Nebulous::Server::Log;
    2525use Nebulous::Server::SQL;
    26 use Params::Validate qw( validate_pos SCALAR SCALARREF UNDEF );
     26use Params::Validate qw( validate validate_pos SCALAR SCALARREF UNDEF BOOLEAN );
    2727use URI::file;
    2828
     
    3737
    3838    # let Nebulous::Server::Config validate our params
    39     my $config = Nebulous::Server::Config->init( @_ );
     39    my $config = Nebulous::Server::Config->new( @_ );
     40
     41    return $class->new_from_config($config);
     42}
     43
     44
     45sub new_from_config
     46{
     47    my ($class, $config) = @_;
    4048
    4149    # log4perl is not avaliable until we call init()
    4250    Nebulous::Server::Log->init($config);
    4351    my $log = Log::Log4perl::get_logger( "Nebulous::Server" );
     52    $log->level($config->trace);
    4453
    4554    my $sql = Nebulous::Server::SQL->new;
     
    5261    $self->config($config);
    5362
    54     # ask for the db handle as a means of validating the database parameters
    55     $self->db;
    56 
    5763    $log->debug( "leaving" );
    58    
     64
    5965    return $self;
    6066}
    6167
    62 
    63 sub db
    64 {
    65     my $self = shift;
    66 
    67     if (@_) {
    68         $self->{db} = $_[0];
    69         return $self;
    70     }
     68# EAM : In the 'distributed' version of Nebulous, there is a collection of N databases
     69# the db_index uniquely defines the db used by a given key
     70sub _db_index_for_key
     71{
     72    my ($self, $key) = @_;
     73
     74    my $config  = $self->config;
     75
     76    my $db_index = 0;
     77    die "key not defined" unless defined $key;
     78
     79    # hash the key to select the correct database instance
     80    # only use the first 8 hex chars... have to be careful to avoid an int
     81    # overflow here
     82
     83    # hash only the directory component of the path and not the filename
     84    my $path = dirname($key->path);
     85    $db_index = unpack("h8", sha1_hex($path)) % $config->n_db;
     86
     87    return $db_index;
     88}
     89
     90sub _db_for_index
     91{
     92    my ($self, $db_index) = @_;
    7193
    7294    my $log     = $self->log;
     
    7496    my $config  = $self->config;
    7597
     98    # lookup to see if we have a stored dbh for this database
     99    my $dbh = $self->{dbs}[$db_index];
    76100    # if the dbh is still alive, return it
    77     if (defined $self->{db} and $self->{db}->ping) {
     101    if (defined $dbh and $dbh->ping) {
    78102        $log->debug("db handle is still alive");
    79         return $self->{db};
     103        return $dbh;
    80104    }
    81105    # otherwise create a new connection
    82106    $log->debug("db handle is dead/unopened");
     107
     108    # lookup database info
     109    my $db_config = $config->db($db_index);
     110    die "can't find database configuration info for database # $db_index"
     111        unless $db_config;
    83112
    84113    # if we're running under mod_perl & Apache::DBI is loaded we want to
     
    87116    # processes and the database might have gone away on us.  Apache::DBI will
    88117    # take care of getting a valid dbh back.
    89     my $db;
    90118    eval {
    91         $db = DBI->connect_cached(
    92             $config->dsn,
    93             $config->dbuser,
    94             $config->dbpasswd,
     119        $dbh = DBI->connect_cached(
     120            $db_config->dsn,
     121            $db_config->dbuser,
     122            $db_config->dbpasswd,
    95123            {
    96124                RaiseError => 1,
     
    100128        );
    101129
    102         $db->do( $sql->set_transaction_model );
    103         $log->debug( "connected to database: ", sub { $db->data_sources; } );
    104         $db->commit;
     130        $dbh->do( $sql->set_transaction_model );
     131        $log->debug( "connected to database: ", sub { $dbh->data_sources; } );
     132        $dbh->commit;
    105133        $log->debug("commit");
    106134    };
    107135    if ( $@ ) {
    108         $db->rollback if $db;
     136        $dbh->rollback if $dbh;
    109137        $log->debug("rollback");
    110138        $log->logdie( "database error: $@" );
    111139    }
    112140
    113     $self->{db} = $db;
    114 
    115     return $db;
    116 }
    117 
     141    $self->{dbs}[$db_index] = $dbh;
     142
     143    return $dbh;
     144}
     145
     146sub db
     147{
     148    my $self = shift;
     149
     150    my ($key) = validate_pos(@_,
     151        {
     152            isa => 'Nebulous::Key',
     153        },
     154    );
     155
     156    my $log     = $self->log;
     157    my $sql     = $self->sql;
     158    my $config  = $self->config;
     159
     160    die "key not defined" unless defined $key;
     161    my $db_index = $self->_db_index_for_key($key);
     162
     163    my $dbh = $self->_db_for_index($db_index);
     164    return $dbh;
     165}
    118166
    119167sub create_object
     
    138186    );
    139187
    140     my $log = $self->log;
    141     my $sql = $self->sql;
    142     my $db  =$self->db;
    143 
    144     $log->debug( "entered - @_" );
    145 
    146188    # vol_name overrides the key implied volume
    147189    $key = parse_neb_key($key, $vol_name);
    148190    $vol_name = $key->volume;
    149191
     192    my $log = $self->log;
     193    my $sql = $self->sql;
     194    my $db  = $self->db($key);
     195
     196    $log->debug( "entered - @_" );
     197
    150198    # the key's volume can't be validiated on input for this method so we have
    151199    # to check it after parsing the key
    152200    if (defined $vol_name
    153         and not $self->_is_valid_volume_name($key->volume)) {
     201        and not $self->_is_valid_volume_name($key, $key->volume)) {
    154202        if ($key->soft_volume) {
    155203            $log->warn( "$vol_name is not a known volume name" );
     
    161209       
    162210    my ($vol_id, $vol_host, $vol_path, $vol_xattr)
    163         = $self->_get_storage_volume($vol_name, $key->soft_volume);
     211        = $self->_get_storage_volume($key, $vol_name, $key->soft_volume);
     212
     213    my $parent_id = $self->_resolve_dir_parent_id(key => $key, create => 1);
    164214
    165215    my $uri;
     
    169219                # create storage_object
    170220                my $query = $db->prepare_cached( $sql->new_object );
    171                 $query->execute('NULL', $key->path);
     221                $query->execute('NULL', $key->path, basename($key->path), $parent_id);
    172222            }
    173223
     
    215265
    216266            # TODO add some stuff here to retry if unsucessful
    217             $uri = $self->_create_empty_instance_file($key->path, $so_id, $ins_id, $vol_path, $vol_xattr);
     267            $uri = $self->_create_empty_instance_file($key, $so_id, $ins_id, $vol_path, $vol_xattr);
    218268            $log->debug("created $uri on volume ID: $vol_id");
    219269
     
    247297
    248298
     299sub _resolve_dir_parent_id
     300{
     301    my $self = shift;
     302
     303    my %p = validate(@_,
     304        {
     305            key     => {
     306                isa         => 'Nebulous::Key',
     307            },
     308            create  => {
     309                type        => BOOLEAN,
     310                optional    => 1,
     311                default     => undef,
     312            },
     313            # return dir_id instead of parent_id
     314            dir_id  => {
     315                type        => BOOLEAN,
     316                optional    => 1,
     317                default     => undef,
     318            },
     319        }
     320    );
     321
     322    my $key = $p{key};
     323
     324    my $log = $self->log;
     325    my $sql = $self->sql;
     326    my $db  = $self->db($key);
     327
     328    $log->debug( "entered - @_" );
     329
     330    # no path means '/', which has a dir_id & parent_id of 1
     331    return 1 if $key->path eq '';
     332
     333    # resolve parent directory
     334    my @dirs;
     335
     336    # File::Spec->splitpath was causing ->splitdir to always an extra dir
     337    # named "" because of a trailing /
     338    unless ($p{dir_id}) {
     339        @dirs = File::Spec->splitdir(dirname($key->path));
     340    } else {
     341        @dirs = File::Spec->splitdir($key->path);
     342    }
     343    # dirname returns "." if there is no dir component to the path, we have
     344    # to filter this out
     345    @dirs = grep(!/^\.$/, @dirs);
     346
     347    $log->debug("looking for dirs - ", join(" : ", @dirs), "\n");
     348
     349    # start at the root dir; '/' == 1
     350    my $parent_id = 1;
     351    my $dir_id;
     352TRANS: while (1) {
     353        eval {
     354            foreach my $dir (@dirs) {
     355                $dir_id = undef;
     356                {
     357                    my $query = $db->prepare_cached($sql->get_directory);
     358                    $query->execute($parent_id, $dir);
     359                    if ($query->rows) {
     360                        $dir_id = $query->fetchrow_hashref->{'dir_id'};
     361                        $log->debug("resolved $dir to dir_id: $dir_id");
     362                    }
     363                    $query->finish;
     364                }
     365
     366                # if we found a dir_id, a row for this directory already exists
     367                if (defined $dir_id) {
     368                    $parent_id = $dir_id;
     369                    # note that you can't exit an eval {} with next
     370                    next;
     371                }
     372
     373                # else dir doesn't exist
     374                unless ($p{create}) {
     375                    # resolution failed
     376                    $parent_id = undef;
     377                    last;
     378                }
     379
     380                {
     381                    # dir doesn't exist, create it
     382                    my $query = $db->prepare_cached($sql->new_directory);
     383                    $query->execute($dir, $parent_id);
     384                }
     385
     386                # get the dir_id of the new directory entry
     387                {
     388                    my $query = $db->prepare_cached($sql->last_insert_id);
     389                    $query->execute();
     390
     391                    # the new dir_id will be the parent_id of the next
     392                    # descendent directory
     393                    ($parent_id) = $query->fetchrow_array;
     394                    $query->finish;
     395                }
     396                $log->logdie("failed to get LAST_INSERT_ID()")
     397                    unless $parent_id;
     398
     399                $db->commit;
     400            }
     401        };
     402        if ($@) {
     403            $db->rollback;
     404            $log->debug("rollback");
     405            if ($@ =~ /Deadlock found/) {
     406                $log->warn("database deadlock retrying transaction: $@");
     407                redo TRANS;
     408            }
     409            $log->logdie("error: $@");
     410        }
     411        last;
     412    }
     413
     414    $log->debug("leaving");
     415
     416    return $p{dir_id} ? $dir_id : $parent_id;
     417}
     418
     419
    249420sub rename_object
    250421{
     
    266437        },
    267438    );
    268 
    269     my $log = $self->log;
    270     my $sql = $self->sql;
    271     my $db  =$self->db;
    272 
    273     $log->debug("entered - @_");
    274439
    275440    # ignore volumes
    276441    $key    = parse_neb_key($key);
    277442    $newkey = parse_neb_key($newkey);
     443
     444    my $log = $self->log;
     445    my $sql = $self->sql;
     446    my $db  = $self->db($key);
     447
     448    $log->debug("entered - @_");
     449
     450    # XXX this may require database migration in the future
     451    unless ($self->_db_index_for_key($key)
     452         == $self->_db_index_for_key($newkey)) {
     453        $log->logdie("can not rename objects across distributed database boundaries");
     454    }
    278455
    279456TRANS: while (1) {
     
    282459            my $query = $db->prepare_cached($sql->rename_object);
    283460            # this SQL statment takes the new key name as the first param
    284             my $rows = $query->execute($newkey->path, $key->path);
     461            my $rows = $query->execute($newkey->path, basename($newkey->path), $self->_resolve_dir_parent_id(key => $newkey, create => 1), $key->path);
    285462
    286463            # if we affected more then one row something very bad has happened.
     
    310487}
    311488
    312 
    313489sub swap_objects
    314490{
     
    329505        },
    330506    );
    331 
    332     my $log = $self->log;
    333     my $sql = $self->sql;
    334     my $db  =$self->db;
    335 
    336     $log->debug("entered - @_");
    337507
    338508    # ignore volumes
     
    340510    $key2 = parse_neb_key($key2);
    341511
    342     # order of operations for the swap:
     512    my $log = $self->log;
     513    my $sql = $self->sql;
     514
     515    my $dbidx1 = $self->_db_index_for_key($key1);
     516    my $dbidx2 = $self->_db_index_for_key($key2);
     517    die "cannot swap keys not stored on the same database" unless ($dbidx1 == $dbidx2);
     518
     519    my $dbh1 = $self->_db_for_index($dbidx1);
     520    my $dbh2 = $self->_db_for_index($dbidx2);
     521    die "different db handles for the same db?" unless ($dbh1 == $dbh2);
     522
     523    $log->debug("entered - @_");
     524
     525    # order of operations for the swap with a single db is:
    343526    # key1 -> key1.swap
    344527    # key2 -> key1
    345528    # key1.swap -> key2
    346529
    347 TRANS: while (1) {
     530    my $db = $dbh1;
     531  TRANS: while (1) {
    348532        eval {
    349533            {
    350                 # key1 -> key1.swap
    351                 my $query = $db->prepare_cached($sql->rename_object);
    352                 # this SQL statment takes the new key name as the first param
    353                 my $rows = $query->execute($key1->path . ".swap", $key1->path);
    354 
    355                 # if we affected more then one row something very bad has happened.
    356                 unless ($rows == 1) {
    357                     $query->finish;
    358                     $log->logdie("affected row count is $rows instead of 1");
    359                 }
    360             }
    361 
    362             {
    363                 # key2 -> key1
    364                 my $query = $db->prepare_cached($sql->rename_object);
    365                 # this SQL statment takes the new key name as the first param
    366                 my $rows = $query->execute($key1->path, $key2->path);
    367 
    368                 # if we affected more then one row something very bad has happened.
    369                 unless ($rows == 1) {
    370                     $query->finish;
    371                     $log->logdie("affected row count is $rows instead of 1");
    372                 }
    373             }
    374 
    375             {
    376                 # key1.swap -> key2
    377                 my $query = $db->prepare_cached($sql->rename_object);
    378                 # this SQL statment takes the new key name as the first param
    379                 my $rows = $query->execute($key2->path, $key1->path . ".swap");
    380 
    381                 # if we affected more then one row something very bad has happened.
    382                 unless ($rows == 1) {
    383                     $query->finish;
    384                     $log->logdie("affected row count is $rows instead of 1");
    385                 }
    386             }
     534              # key1 -> key1.swap
     535              my $query = $db->prepare_cached($sql->rename_object);
     536              # this SQL statment takes the new key name as the first param
     537              # XXX currently using a bogus dir_id -- this may cause a problem
     538              # someday but it's unlikley as it's contained entirely in the
     539              # transaction
     540              my $rows = $query->execute($key1->path . ".swap", basename($key1->path) . ".swap", 1, $key1->path);
     541
     542              # if we affected more then one row something very bad has happened.
     543              unless ($rows == 1) {
     544                  $query->finish;
     545                  $log->logdie("affected row count is $rows instead of 1");
     546              }
     547          }
     548
     549          {
     550              # key2 -> key1
     551              my $query = $db->prepare_cached($sql->rename_object);
     552              # this SQL statment takes the new key name as the first param
     553              my $rows = $query->execute($key1->path, basename($key1->path), $self->_resolve_dir_parent_id(key => $key1, create => 1), $key2->path);
     554
     555              # if we affected more then one row something very bad has happened.
     556              unless ($rows == 1) {
     557                  $query->finish;
     558                  $log->logdie("affected row count is $rows instead of 1");
     559              }
     560          }
     561
     562          {
     563              # key1.swap -> key2
     564              my $query = $db->prepare_cached($sql->rename_object);
     565              # this SQL statment takes the new key name as the first param
     566              my $rows = $query->execute($key2->path, basename($key2->path), $self->_resolve_dir_parent_id(key => $key2, create => 1), $key1->path . ".swap");
     567
     568              # if we affected more then one row something very bad has happened.
     569              unless ($rows == 1) {
     570                  $query->finish;
     571                  $log->logdie("affected row count is $rows instead of 1");
     572              }
     573          }
    387574
    388575            $db->commit;
     
    398585            $log->logdie("database error: $@");
    399586        }
    400         last;
    401     }
     587      last;
     588  }
    402589
    403590    $log->debug("leaving");
     
    406593}
    407594
     595# EAM : from JH, below is a possible option to swap instances across
     596# dbs.  I recommend that this action be disallowed, and instead such
     597# operations be implemented only as a combination of copy and delete
     598
     599# order of operations for the swap between two dbs is:
     600# key1 start transaction
     601# key1 -> read all instances
     602# key1 -> remove all instances
     603# key2 start transaction
     604# key2 -> read all instances
     605# key2 -> remove all instances
     606# key1 -> insert key 2 instances
     607# key2 -> insert key 1 instances
     608# key1,2 commit
    408609
    409610sub replicate_object
     
    440641    # then we should throw an error
    441642
    442     my $log = $self->log;
    443     my $sql = $self->sql;
    444     my $db  =$self->db;
    445 
    446     $log->debug("entered - @_");
    447 
    448643    # vol_name overrides the key implied volume
    449644    $key = parse_neb_key($key, $vol_name);
    450645    $vol_name = $key->volume;
    451646
     647    my $log = $self->log;
     648    my $sql = $self->sql;
     649    my $db  = $self->db($key);
     650
     651    $log->debug("entered - @_");
     652
    452653    if (defined $vol_name
    453         and not $self->_is_valid_volume_name($key->volume)) {
     654        and not $self->_is_valid_volume_name($key, $key->volume)) {
    454655        if ($key->soft_volume) {
    455656            $log->warn( "$vol_name is not a known volume name" );
     
    463664    if (defined $vol_name) {
    464665        ($vol_id, $vol_host, $vol_path, $vol_xattr)
    465             = $self->_get_storage_volume($vol_name);
     666            = $self->_get_storage_volume($key, $vol_name);
    466667    } else {
    467668        ($vol_id, $vol_host, $vol_path, $vol_xattr)
     
    508709
    509710            # TODO add some stuff here to retry if unsucessful
    510             $uri = $self->_create_empty_instance_file($key->path, $so_id, $ins_id, $vol_path, $vol_xattr);
     711            # XXX if this fails, it should try to generate the
     712            # instance on another volume (unless !$soft_volume)
     713            $uri = $self->_create_empty_instance_file($key, $so_id, $ins_id, $vol_path, $vol_xattr);
    511714
    512715            {
     
    561764    );
    562765
    563     my $log = $self->log;
    564     my $sql = $self->sql;
    565     my $db  =$self->db;
    566 
    567     $log->debug( "entered - @_" );
    568 
    569766    # ignore volume
    570767    $key = parse_neb_key($key);
     768
     769    my $log = $self->log;
     770    my $sql = $self->sql;
     771    my $db  = $self->db($key);
     772
     773    $log->debug( "entered - @_" );
    571774
    572775    my $so_id;
     
    671874    );
    672875
    673     my $log = $self->log;
    674     my $sql = $self->sql;
    675     my $db  =$self->db;
    676 
    677     $log->debug( "entered - @_" );
    678 
    679876    # ignore volume
    680877    $key = parse_neb_key($key);
     878
     879    my $log = $self->log;
     880    my $sql = $self->sql;
     881    my $db  = $self->db($key);
     882
     883    $log->debug( "entered - @_" );
    681884
    682885    my $so_id;
     
    790993    );
    791994
    792     my $log = $self->log;
    793     my $sql = $self->sql;
    794     my $db  =$self->db;
    795 
    796     $log->debug("entered - @_");
    797 
    798995    # ignore volume
    799996    $key = parse_neb_key($key);
     997
     998    my $log = $self->log;
     999    my $sql = $self->sql;
     1000    my $db  = $self->db($key);
     1001
     1002    $log->debug("entered - @_");
    8001003
    8011004TRANS: while (1) {
     
    8641067    );
    8651068
    866     my $log = $self->log;
    867     my $sql = $self->sql;
    868     my $db  =$self->db;
    869 
    870     $log->debug("entered - @_");
    871 
    8721069    # ignore volume
    8731070    $key = parse_neb_key($key);
     1071
     1072    my $log = $self->log;
     1073    my $sql = $self->sql;
     1074    my $db  = $self->db($key);
     1075
     1076    $log->debug("entered - @_");
    8741077
    8751078    my $value;
     
    9171120    );
    9181121
    919     my $log = $self->log;
    920     my $sql = $self->sql;
    921     my $db  =$self->db;
    922 
    923     $log->debug("entered - @_");
    924 
    9251122    # ignore volume
    9261123    $key = parse_neb_key($key);
     1124
     1125    my $log = $self->log;
     1126    my $sql = $self->sql;
     1127    my $db  = $self->db($key);
     1128
     1129    $log->debug("entered - @_");
    9271130
    9281131    my @xattrs;
     
    9601163    );
    9611164
    962     my $log = $self->log;
    963     my $sql = $self->sql;
    964     my $db  =$self->db;
    965 
    966     $log->debug("entered - @_");
    967 
    9681165    # ignore volume
    9691166    $key = parse_neb_key($key);
     1167
     1168    my $log = $self->log;
     1169    my $sql = $self->sql;
     1170    my $db  = $self->db($key);
     1171
     1172    $log->debug("entered - @_");
    9701173
    9711174TRANS: while (1) {
     
    10011204}
    10021205
    1003 
     1206# loop over all db_index values, passing db_index to each call
    10041207sub find_objects
    10051208{
    10061209    my $self = shift;
    10071210
    1008     my ( $pattern ) = validate_pos( @_,
     1211    my ($pattern) = validate_pos( @_,
    10091212        {
    10101213            type        => SCALAR,
     
    10131216    );
    10141217
    1015     my $log = $self->log;
    1016     my $sql = $self->sql;
    1017     my $db  =$self->db;
     1218    $pattern = parse_neb_key($pattern);
     1219
     1220    my $log = $self->log;
    10181221
    10191222    $log->debug( "entered - @_" );
    10201223
    1021     unless ($pattern) {
     1224    unless (defined $pattern) {
    10221225        $log->debug( "leaving" );
    10231226        $log->logdie("no keys found");
    10241227    }
    10251228
    1026     # attempt to strip off neb:// if it exists
    1027     $pattern =~ s|^neb:||;
    1028 
     1229    my @keys = ();
     1230    my $n_dbs = $self->config->n_db();
     1231    for (my $index = 0; $index < $n_dbs; $index ++) {
     1232        my $newkeys = $self->_find_objects_for_index($index, $pattern);
     1233        push @keys, @$newkeys;
     1234    }
     1235    $log->logdie("no keys found") unless ( scalar @keys );
     1236
     1237    $log->debug( "leaving" );
     1238
     1239    return \@keys;
     1240}
     1241
     1242# find matching objects from the given server
     1243sub _find_objects_for_index
     1244{
     1245
     1246    my $self    = shift;
     1247    my $index   = shift;
     1248    my $key     = shift;
     1249
     1250    my $log = $self->log;
     1251    my $sql = $self->sql;
     1252    my $db  = $self->_db_for_index($index);
     1253
     1254    $log->debug( "entered - @_" );
     1255
     1256    # first check to see if the key is an exact match
    10291257    my @keys;
    10301258    eval {
    1031         my $query = $db->prepare_cached( $sql->find_objects );
    1032         $query->execute( $pattern );
     1259        $log->debug("trying for an exact key match with $key");
     1260        my $query = $db->prepare_cached( $sql->find_object_by_ext_id );
     1261        $query->execute( $key->path );
     1262        if ($query->rows) {
     1263            my $ext_id = $query->fetchrow_hashref->{'ext_id'};
     1264            $log->debug( "pattern has an exact match" );
     1265            push @keys, $ext_id;
     1266        } else {
     1267            $log->debug("no exact match for key");
     1268        }
     1269        $query->finish;
     1270    };
     1271    if ($@) {
     1272        $db->rollback;
     1273        $log->logdie("database error: $@");
     1274    }
     1275
     1276    if (scalar @keys) {
     1277        # it was an exact match, so stop here
     1278        $log->debug("leaving");
     1279
     1280        return \@keys;
     1281    }
     1282
     1283    # else, assume it's a directory
     1284    my $dir_id = $self->_resolve_dir_parent_id(key => $key, dir_id => 1);
     1285    unless (defined $dir_id) {
     1286        $log->logdie("pattern $key does not match any key or directory");
     1287    }
     1288
     1289    eval {
     1290        $log->debug("trying for a directory match under dir: $dir_id");
     1291        my $query = $db->prepare_cached( $sql->find_object_by_dir_id );
     1292        $query->execute( $dir_id );
    10331293
    10341294        while ( my $row = $query->fetchrow_hashref ) {
    10351295            my $key = $row->{ 'ext_id' };
    10361296            push @keys, $key if $key;
     1297            $log->debug( "matched $key" ) if $key;
    10371298        }
    10381299    };
    10391300    $log->logdie("database error: $@") if $@;
    1040 
    1041     $log->logdie("no keys found") unless ( scalar @keys );
    10421301
    10431302    $log->debug( "leaving" );
     
    10711330    );
    10721331
    1073     my $log = $self->log;
    1074     my $sql = $self->sql;
    1075     my $db  =$self->db;
    1076 
    1077     $log->debug("entered - @_");
    1078 
    10791332    # vol_name overrides the key implied volume
    10801333    $key = parse_neb_key($key, $vol_name);
    10811334    $vol_name = $key->volume;
    10821335
     1336    my $log = $self->log;
     1337    my $sql = $self->sql;
     1338    my $db  = $self->db($key);
     1339
     1340    $log->debug("entered - @_");
     1341
    10831342    # the key's volume can't be validiated on input for this method so we have
    10841343    # to check it after parsing the key
    10851344    if (defined $vol_name
    1086         and not $self->_is_valid_volume_name($key->volume)) {
     1345        and not $self->_is_valid_volume_name($key, $key->volume)) {
    10871346        if ($key->soft_volume) {
    10881347            $log->warn( "$vol_name is not a known volume name" );
     
    11441403    my $self = shift;
    11451404
    1146     my ( $uri ) = validate_pos( @_,
     1405    my ($key, $uri) = validate_pos( @_,
     1406        {
     1407            type        => SCALAR,
     1408            callbacks   => {
     1409                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
     1410            },
     1411        },
    11471412        {
    11481413            type => SCALAR|SCALARREF,
     
    11501415    );
    11511416
    1152     my $log = $self->log;
    1153     my $sql = $self->sql;
    1154     my $db  =$self->db;
     1417    # ignore volume
     1418    $key = parse_neb_key($key);
     1419
     1420    my $log = $self->log;
     1421    my $sql = $self->sql;
     1422    my $db  = $self->db($key);
    11551423
    11561424    $log->debug( "entered - @_" );
     
    12441512    );
    12451513
    1246     my $log = $self->log;
    1247     my $sql = $self->sql;
    1248     my $db  =$self->db;
    1249 
    1250     $log->debug("entered - @_");
    1251 
    12521514    # ignore volume
    12531515    $key = parse_neb_key($key);
     1516
     1517    my $log = $self->log;
     1518    my $sql = $self->sql;
     1519    my $db  = $self->db($key);
     1520
     1521    $log->debug("entered - @_");
    12541522
    12551523    my $stat;
     
    12721540}
    12731541
    1274 
     1542# this should have a 'db_index' as an argument
    12751543sub mounts
    12761544{
     1545    # XXX: this will only pull the mounts from one db
     1546    # XXX: loop over db_index and generate a single unique list
     1547    # XXX: or report mount info for each db server
    12771548    my $self = shift;
    12781549
     
    12811552    my $log = $self->log;
    12821553    my $sql = $self->sql;
    1283     my $db  =$self->db;
     1554    my $db  = $self->_db_for_index(0); # XXX fix as above
    12841555
    12851556    $log->debug("entered - @_");
     
    13101581    my $self = shift;
    13111582
    1312     my $log = $self->log;
    1313     my $sql = $self->sql;
    1314     my $db  = $self->db;
     1583    my ($key, $name, $soft_volume) = @_;
     1584
     1585    my $log = $self->log;
     1586    my $sql = $self->sql;
     1587    my $db  = $self->db($key);
    13151588
    13161589    no warnings qw( uninitialized );
    13171590    $log->debug( "entered - @_" );
    13181591    use warnings;
    1319 
    1320     my ($name, $soft_volume) = @_;
    13211592
    13221593    my ($vol_id, $vol_host, $vol_path, $xattr);
     
    13351606                # find it, fall back to any volume
    13361607                if ($soft_volume) {
    1337                     ($vol_id, $vol_host, $vol_path, $xattr) = $self->_get_storage_volume;
     1608                    ($vol_id, $vol_host, $vol_path, $xattr) = $self->_get_storage_volume($key);
    13381609                    return; # this just returns out of the eval not from the subroutine
    13391610                }
     
    13751646    my $self = shift;
    13761647
    1377     my $log = $self->log;
    1378     my $sql = $self->sql;
    1379     my $db  =$self->db;
     1648    my $key = shift;
     1649
     1650    my $log = $self->log;
     1651    my $sql = $self->sql;
     1652    my $db  = $self->db($key);
    13801653
    13811654    no warnings qw( uninitialized );
    13821655    $log->debug( "entered - @_" );
    13831656    use warnings;
    1384 
    1385     my $key = shift;
    1386 
    1387     $key = parse_neb_key($key);
    13881657
    13891658    my ($vol_id, $vol_host, $vol_path, $xattr);
     
    14231692    my ($self, $key) = @_;
    14241693
    1425     my $log = $self->log;
    1426     my $sql = $self->sql;
    1427     my $db  =$self->db;
    1428 
    14291694    $key = parse_neb_key($key);
     1695
     1696    my $log = $self->log;
     1697    my $sql = $self->sql;
     1698    my $db  = $self->db($key);
    14301699
    14311700    my $ext_id;
     
    14521721sub _is_valid_volume_name
    14531722{
    1454     my ($self, $vol_name) = @_;
    1455 
    1456     my $log = $self->log;
    1457     my $sql = $self->sql;
    1458     my $db  =$self->db;
    1459 
     1723    my ($self, $key, $vol_name) = @_;
     1724
     1725    $key = parse_neb_key($key);
    14601726    my $volume_info = parse_neb_volume($vol_name);
     1727
     1728    my $log = $self->log;
     1729    my $sql = $self->sql;
     1730    my $db  = $self->db($key);
    14611731
    14621732    $vol_name = $volume_info->{volume};
     
    14931763    my $log = $self->log;
    14941764    my $sql = $self->sql;
    1495     my $db  = $self->db;
     1765    my $db  = $self->db($key);
    14961766
    14971767    my $uri;
    14981768    eval {
    1499         my $storage_path = $self->_generate_storage_path($key, $vol_path);
    1500         my $storage_filename = $self->_generate_storage_filename($key, $ins_id);
     1769        my $storage_path = $self->_generate_storage_path($key->path, $vol_path);
     1770        my $storage_filename = $self->_generate_storage_filename($key->path, $ins_id);
    15011771        unless (-d $storage_path) {
    15021772            _retry(sub { mkpath(@_) }, $storage_path, 0, 0775)
     
    15071777        my $mode = [_retry(sub { stat($storage_path) } )]->[2] & 07777;
    15081778        unless ($mode == 0775) {
    1509             $log->error("$storage_path has the wrong permissions of: %04o", $mode);
     1779            $log->error("$storage_path has the wrong permissions of: %04x", $mode);
    15101780            _retry(sub { chmod(0775, $storage_path) }) or die "can't chmod $storage_path: $!";
    15111781        }
     
    15231793        my $path = $uri->file;
    15241794        die "can not set xattr on $path: $!"
    1525             unless (setfattr($path, 'user.nebulous_key', $key));
     1795            unless (setfattr($path, 'user.nebulous_key', $key->path));
    15261796    }
    15271797
     
    15791849
    15801850    my ($key, $vol_path) = @_;
    1581 
    1582     # if the key has '/' in it, hash only the dirname() component
    1583     if ($key =~ m|/|) {
    1584         $key = dirname($key);
    1585     }
    15861851
    15871852    # taken and modified from Cache::File::cache_file_path()
     
    16271892    my $log = $self->log;
    16281893    my $sql = $self->sql;
    1629     my $db  =$self->db;
     1894#    my $db  = $self->db;
    16301895
    16311896    $log->debug( "entered" );
    16321897
    1633     $self->db->disconnect;       
    1634 
    1635     $log->debug( "disconnected from database: ", sub { $db->data_sources; } );
     1898# XXX do we need to loop over db_index?
     1899#    $self->db->disconnect;       
     1900
     1901#    $log->debug( "disconnected from database: ", sub { $db->data_sources; } );
    16361902
    16371903    $log->debug( "leaving" );
  • trunk/Nebulous-Server/lib/Nebulous/Server.pod

    r20092 r23932  
    2626    Nebulous::Server->find_objects( $pattern );
    2727    Nebulous::Server->find_instances( $key, $volume );
    28     Nebulous::Server->delete_instance( $uri );
     28    Nebulous::Server->delete_instance( $key, $uri );
    2929    Nebulous::Server->stat_object( $key );
    3030    Nebulous::Server->mounts();
     
    160160Throws an exception on error.
    161161
    162 =item * delete_instance( $uri );
    163 
    164 Accepts 1 parameters, it is mandatory.  Returns Boolean true.  Throws an
    165 exception on error.
     162=item * delete_instance( $key, $uri );
     163
     164Accepts 2 parameters, both mandatory.  Returns Boolean true.  C<<$uri>> must be
     165an instance of C<<$key>>.  Throws an exception on error.
    166166
    167167=item * swap_objects( $key1, $key2 );
  • trunk/Nebulous-Server/lib/Nebulous/Server/Config.pm

    r20990 r23932  
    88use warnings FATAL => qw( all );
    99
    10 our $VERSION = 0.02;
     10our $VERSION = 0.03;
    1111
    1212use base qw( Class::Accessor::Fast );
    1313
    1414use Log::Log4perl qw( :levels );
    15 use Params::Validate qw( validate SCALAR );
     15use Params::Validate qw( validate validate_pos SCALAR );
    1616
    1717our %LEVELS = (
     
    2525);
    2626
    27 my $new_validate = {
     27my $db_validate = {
     28    dbindex       => {
     29        type => SCALAR,
     30        regex => qr/^\d+$/,
     31    },
    2832    dsn         => { type => SCALAR },
    2933    dbuser      => { type => SCALAR },
    3034    dbpasswd    => { type => SCALAR },
    31     log_level   => {
     35};
     36
     37my $new_validate = {
     38    trace       => {
    3239        type        => SCALAR,
    3340        optional    => 1,
    34         default     => 'all',
     41        default     => 'fatal',
    3542        callbacks   => {
    3643            'is valid level' => sub {
     
    3946        },
    4047    },
     48    dsn         => { type => SCALAR, optional => 1 },
     49    dbuser      => { type => SCALAR, optional => 1 },
     50    dbpasswd    => { type => SCALAR, optional => 1 },
    4151};
    4252
    4353__PACKAGE__->mk_ro_accessors( keys %$new_validate );
    4454
    45 sub init {
     55
     56sub new
     57{
    4658    my $class = shift;
    4759
     
    4961
    5062    # normalize log levels to lower-case
    51     $p{ log_level } = lc $p{ log_level };
    52 
    53     my $self = \%p;
     63    my $self = { trace => $LEVELS{lc($p{trace})} };
    5464
    5565    bless $self, $class || ref $class;
     66
     67    my @dbs;
     68    $self->{dbs} = \@dbs;
     69
     70    if (defined $p{dsn} or defined $p{dbuser} or defined $p{dbpasswd}) {
     71        $self->add_db(
     72            dbindex     => 0,
     73            dsn         => $p{dsn},
     74            dbuser      => $p{dbuser},
     75            dbpasswd    => $p{dbpasswd},
     76        );
     77    }
    5678
    5779    return $self;
    5880}
    5981
     82
     83sub add_db
     84{
     85    my $self = shift;
     86   
     87    my %p = validate( @_, $db_validate );
     88
     89    my $config_db = Nebulous::Server::Config::DB->new({
     90        dsn         => $p{dsn},
     91        dbuser      => $p{dbuser},
     92        dbpasswd    => $p{dbpasswd},
     93    });
     94
     95    $self->{dbs}->[$p{dbindex}] = $config_db;
     96
     97    return $self;
     98}
     99
     100
     101sub db
     102{
     103    my $self = shift;
     104
     105    my ($db_index) = validate_pos( @_, { type => SCALAR, optional => 1, });
     106
     107    # default to 0
     108    $db_index ||= 0;
     109
     110    return $self->{dbs}->[$db_index];
     111}
     112
     113
     114sub n_db
     115{
     116    my $self = shift;
     117
     118    return scalar @{ $self->{dbs} };
     119}
     120
     121
     122package Nebulous::Server::Config::DB;
     123
     124use strict;
     125use warnings FATAL => qw( all );
     126
     127our $VERSION = 0.01;
     128
     129use base qw( Class::Accessor::Fast );
     130
     131__PACKAGE__->mk_ro_accessors(qw( dsn dbuser dbpasswd ));
     132
    601331;
    61134
  • trunk/Nebulous-Server/lib/Nebulous/Server/Log.pm

    r20990 r23932  
    1616    my ($self, $config) = @_;
    1717
    18     my $dsn         = $config->dsn;
    19     my $dbuser      = $config->dbuser;
    20     my $dbpasswd    = $config->dbpasswd;
     18#    my $dsn         = $config->db->dsn;
     19#    my $dbuser      = $config->db->dbuser;
     20#    my $dbpasswd    = $config->db->dbpasswd;
    2121
    2222    my $conf = <<END;
     
    3030#   date | hostname | priority | method/sub - message\n
    3131
    32     log4perl.appender.SQLLOG            = Log::Log4perl::Appender::DBI
    33     log4perl.appender.SQLLOG.datasource = $dsn
    34     log4perl.appender.SQLLOG.username   = $dbuser
    35     log4perl.appender.SQLLOG.password   = $dbpasswd
    36     log4perl.appender.SQLLOG.sql        = \
     32#    log4perl.appender.SQLLOG            = Log::Log4perl::Appender::DBI
     33#    log4perl.appender.SQLLOG.sql        = \
     34#    log4perl.appender.SQLLOG.datasource =
     35#    log4perl.appender.SQLLOG.username   =
     36#    log4perl.appender.SQLLOG.password   =
    3737    INSERT INTO log (timestamp, hostname, level, sub, message) \
    3838    VALUES          (%d,        %H,       %p,    %M,  %m)
  • trunk/Nebulous-Server/lib/Nebulous/Server/SOAP.pm

    r20990 r23932  
    11# Copyright (c) 2004  Joshua Hoblitt
    22#
    3 # $Id: SOAP.pm,v 1.6 2008-12-14 22:54:25 eugene Exp $
     3# $Id: SOAP.pm,v 1.4.32.1 2008-12-14 22:52:37 eugene Exp $
    44
    55package Nebulous::Server::SOAP;
     
    1717our $AUTOLOAD;
    1818
    19 our @args;
     19our $config;
    2020our $neb;
    2121
    22 sub new_on_init {
     22
     23sub new_on_init
     24{
    2325    my $self = shift;
    2426
     
    2729    require Apache2::ServerUtil;
    2830
    29     @args = @_;
     31    $config = shift;
    3032
    3133    my $s = Apache2::ServerUtil->server;
     
    3537}
    3638
    37 sub init {
     39
     40sub init
     41{
    3842    my $self = shift;
    3943
    40     $neb = Nebulous::Server->new(@args);       
     44    $neb = Nebulous::Server->new_from_config($config);       
    4145
    4246    return Apache2::Const::OK;
    4347}
    4448
    45 sub AUTOLOAD {
     49
     50sub AUTOLOAD
     51{
    4652    my $self = shift;
    4753
     
    7682}
    7783
     84
    78851;
  • trunk/Nebulous-Server/lib/Nebulous/Server/SQL.pm

    r23699 r23932  
    88use warnings FATAL => qw( all );
    99
    10 our $VERSION = '0.02';
     10our $VERSION = '0.04';
    1111
    1212use base qw( Class::Accessor::Fast );
     
    2626    new_object          => qq{
    2727        INSERT INTO storage_object
    28         (so_id, ext_id, type)
    29         VALUES (?, ?, 'REG_FILE')
     28        (so_id, ext_id, ext_id_basename, type, dir_id)
     29        VALUES (?, ?, ?, 'REG_FILE', ?)
    3030    },
    3131    new_object_attr  => qq{
     
    6060        USING (so_id)
    6161        WHERE ext_id = ?
     62    },
     63    get_directory       => qq{
     64        SELECT
     65            dir_id
     66        FROM directory
     67        WHERE parent_id = ?
     68            AND dirname = ?
     69    },
     70    new_directory       => qq{
     71        INSERT INTO directory
     72        (dirname, parent_id)
     73        VALUES (?, ?)
    6274    },
    6375    check_object_name => qq{
     
    297309            USING(vol_id)
    298310    },
    299     find_objects => qq{
    300         SELECT *
    301         FROM storage_object
    302         WHERE ext_id REGEXP ?
     311    find_object_by_ext_id => qq{
     312        SELECT ext_id, ext_id_basename
     313        FROM storage_object
     314        WHERE ext_id = ?
     315    },
     316    find_object_by_dir_id => qq{
     317        SELECT ext_id, ext_id_basename
     318        FROM storage_object
     319        WHERE dir_id = ?
    303320    },
    304321    rename_object => qq{
    305322        UPDATE storage_object
    306         SET ext_id = ?
     323        SET ext_id = ?, ext_id_basename = ?, dir_id = ?
    307324        WHERE ext_id = ?
    308325    },
     
    330347        GROUP BY so_id
    331348        HAVING available_instances < instances OR instances < copies
     349    },
     350    find_objects_with_extra_instances_by_xattr => qq{
     351        SELECT
     352            so.so_id,
     353            so.ext_id,
     354            count(ins_id) as instances,
     355            mv.name as volume_name,
     356            mv.host as volume_host,
     357            count(mv.vol_id) as available_instances,
     358            xattr.value as copies
     359        FROM storage_object AS so
     360        JOIN storage_object_xattr as xattr
     361            ON so.so_id = xattr.so_id
     362            AND xattr.name = 'user.copies'
     363        JOIN instance AS i
     364            ON so.so_id = i.so_id
     365        JOIN mountedvol AS mv
     366            USING(vol_id)
     367        WHERE
     368            mv.available = 1
     369        GROUP BY so_id
     370        HAVING available_instances > copies
     371        limit 5;
    332372    },
    333373    find_objects_with_extra_instances => qq{
     
    387427DROP TABLE IF EXISTS log;
    388428DROP TABLE IF EXISTS mountedvol;
     429DROP TABLE IF EXISTS directory;
    389430DROP PROCEDURE IF EXISTS getmountedvol;
    390431SET FOREIGN_KEY_CHECKS=1
     
    408449
    409450__DATA__
     451CREATE TABLE directory (
     452    dir_id BIGINT NOT NULL AUTO_INCREMENT,
     453    dirname CHAR(255) NOT NULL,
     454    parent_id BIGINT NOT NULL,
     455    FOREIGN KEY(parent_id) REFERENCES directory(dir_id),
     456    PRIMARY KEY(dir_id),
     457    KEY(parent_id)
     458) ENGINE=innodb DEFAULT CHARSET=latin1;
     459
     460###
     461
     462INSERT INTO directory (dir_id, dirname, parent_id) VALUES (1, '/', 1);
     463
     464###
     465
    410466CREATE TABLE storage_object (
    411467    so_id BIGINT NOT NULL AUTO_INCREMENT,
    412468    ext_id VARCHAR(255) NOT NULL UNIQUE,
     469    ext_id_basename VARCHAR(255) NOT NULL,
     470    dir_id BIGINT NOT NULL,
     471    FOREIGN KEY(dir_id) REFERENCES directory(dir_id),
    413472    type enum('REG_FILE'),
    414473    PRIMARY KEY(so_id),
  • trunk/Nebulous-Server/t/01_load.t

    r17076 r23932  
    1212use Test::More tests => 5;
    1313
    14 BEGIN { use_ok( 'Nebulous::Keys' ); }
     14BEGIN { use_ok( 'Nebulous::Key' ); }
    1515BEGIN { use_ok( 'Nebulous::Server' ); }
    1616BEGIN { use_ok( 'Nebulous::Server::Log' ); }
  • trunk/Nebulous-Server/t/02_config.t

    r23931 r23932  
    33# Copryight (C) 2004-2005  Joshua Hoblitt
    44#
    5 # $Id: 02_config.t,v 1.1 2008-12-12 21:13:41 jhoblitt Exp $
     5# $Id: 02_config.t,v 1.1.2.2 2008-12-14 22:52:37 eugene Exp $
    66
    77use strict;
  • trunk/Nebulous-Server/t/02_server_setup.t

    r20990 r23932  
    88use warnings;
    99
    10 use Test::More tests => 2;
     10use Test::More tests => 6;
    1111
    1212use lib qw( ./t ./lib );
     
    1717Test::Nebulous->setup;
    1818
    19 isa_ok(
    20     Nebulous::Server->new(
    21         dsn         => $NEB_DB,
    22         dbuser      => $NEB_USER,
    23         dbpasswd    => $NEB_PASS,
    24     ),
    25     "Nebulous::Server"
    26 );
     19isa_ok(Nebulous::Server->new(), "Nebulous::Server");
    2720
    2821Test::Nebulous->setup;
    2922
    30 eval {
    31     Nebulous::Server->new(
     23# ->new()
     24{
     25    my $neb = Nebulous::Server->new( trace => 'off' );
     26
     27    ok($neb, "set log level");
     28}
     29
     30Test::Nebulous->setup;
     31
     32{
     33    my $neb = Nebulous::Server->new(
    3234        dsn         => "DBI:mysql:database=foobar:host=localhost",
    3335        dbuser      => "baz",
    3436        dbpasswd    =>"boo",
    3537    );
    36 };
    37 like( $@, qr/DBI connect.*? failed/, "bad dsn/user/pass" );
     38
     39    ok($neb, "set database");
     40}
     41
     42Test::Nebulous->setup;
     43
     44# add dbs after ->new()
     45{
     46    my $neb = Nebulous::Server->new;
     47
     48    ok($neb->config->add_db(
     49        dbindex    => 0,
     50        dsn         => "DBI:mysql:database=foobar:host=localhost",
     51        dbuser      => "baz",
     52        dbpasswd    =>"boo",
     53    ), "add db");
     54   
     55    ok($neb->config->add_db(
     56        dbindex    => 1,
     57        dsn         => "DBI:mysql:database=foobar:host=localhost",
     58        dbuser      => "baz",
     59        dbpasswd    =>"boo",
     60    ), "add dbs");
     61
     62    is($neb->config->n_db, 2, "n dbs")
     63}
    3864
    3965Test::Nebulous->cleanup;
  • trunk/Nebulous-Server/t/03_server_create_object.t

    r19493 r23932  
    88use warnings FATAL => qw( all );
    99
    10 use Test::More tests => 89;
     10use Test::More tests => 99;
    1111
    1212use lib qw( ./t ./lib );
    1313
     14use File::Basename qw( basename );
    1415use File::ExtAttr qw( getfattr );
    1516use Nebulous::Server;
     
    2627);
    2728
     29use Test::DBUnit dsn => $NEB_DB, username => $NEB_USER, password => $NEB_PASS;
     30
    2831Test::Nebulous->setup;
    2932
     
    334337}
    335338
     339# test for properly row creation in the directories table
     340
     341Test::Nebulous->setup;
     342
     343{
     344    my $key = "foo";
     345    $neb->create_object($key);
     346
     347    expected_dataset_ok(
     348        directory       => [dir_id => 1, dirname => '/', parent_id => 1],
     349        storage_object  => [so_id => 1, ext_id => $key, dir_id => 1],
     350    );
     351}
     352
     353Test::Nebulous->setup;
     354
     355{
     356    my $key = "a/foo";
     357    $neb->create_object($key);
     358
     359    expected_dataset_ok(
     360        directory       => [dir_id => 1, dirname => '/', parent_id => 1],
     361        directory       => [dir_id => 2, dirname => 'a', parent_id => 1],
     362        storage_object  => [so_id => 1, ext_id => $key, ext_id_basename => basename($key), dir_id => 2],
     363    );
     364
     365}
     366
     367Test::Nebulous->setup;
     368
     369{
     370    my $key = "a/b/foo";
     371    $neb->create_object($key);
     372
     373    expected_dataset_ok(
     374        directory       => [dir_id => 1, dirname => '/', parent_id => 1],
     375        directory       => [dir_id => 2, dirname => 'a', parent_id => 1],
     376        directory       => [dir_id => 3, dirname => 'b', parent_id => 2],
     377        storage_object  => [so_id => 1, ext_id => $key, ext_id_basename => basename($key), dir_id => 3],
     378    );
     379}
     380
     381Test::Nebulous->setup;
     382
     383{
     384    my $key = "a/b/c/foo";
     385    $neb->create_object($key);
     386
     387    expected_dataset_ok(
     388        directory       => [dir_id => 1, dirname => '/', parent_id => 1],
     389        directory       => [dir_id => 2, dirname => 'a', parent_id => 1],
     390        directory       => [dir_id => 3, dirname => 'b', parent_id => 2],
     391        directory       => [dir_id => 4, dirname => 'c', parent_id => 3],
     392        storage_object  => [so_id => 1, ext_id => $key, ext_id_basename => basename($key), dir_id => 4],
     393    );
     394}
     395
     396Test::Nebulous->setup;
     397
     398{
     399    my $key1 = "a/b/c/foo";
     400    my $key2 = "foo";
     401    $neb->create_object($key1);
     402    $neb->create_object($key2);
     403
     404    expected_dataset_ok(
     405        directory       => [dir_id => 1, dirname => '/', parent_id => 1],
     406        storage_object  => [so_id => 2, ext_id => $key2, ext_id_basename => basename($key2), dir_id => 1],
     407        directory       => [dir_id => 2, dirname => 'a', parent_id => 1],
     408        directory       => [dir_id => 3, dirname => 'b', parent_id => 2],
     409        directory       => [dir_id => 4, dirname => 'c', parent_id => 3],
     410        storage_object  => [so_id => 1, ext_id => $key1, ext_id_basename => basename($key1), dir_id => 4],
     411    );
     412}
     413
     414Test::Nebulous->setup;
     415
     416{
     417    my $key1 = "a/b/c/foo";
     418    my $key2 = "a/foo";
     419    $neb->create_object($key1);
     420    $neb->create_object($key2);
     421
     422    expected_dataset_ok(
     423        directory       => [dir_id => 1, dirname => '/', parent_id => 1],
     424        directory       => [dir_id => 2, dirname => 'a', parent_id => 1],
     425        storage_object  => [so_id => 2, ext_id => $key2, ext_id_basename => basename($key2), dir_id => 2],
     426        directory       => [dir_id => 3, dirname => 'b', parent_id => 2],
     427        directory       => [dir_id => 4, dirname => 'c', parent_id => 3],
     428        storage_object  => [so_id => 1, ext_id => $key1, ext_id_basename => basename($key1), dir_id => 4],
     429    );
     430}
     431
     432Test::Nebulous->setup;
     433
     434{
     435    my $key1 = "a/b/c/foo";
     436    my $key2 = "d/foo";
     437    $neb->create_object($key1);
     438    $neb->create_object($key2);
     439
     440    expected_dataset_ok(
     441        directory       => [dir_id => 1, dirname => '/', parent_id => 1],
     442        directory       => [dir_id => 2, dirname => 'a', parent_id => 1],
     443        directory       => [dir_id => 3, dirname => 'b', parent_id => 2],
     444        directory       => [dir_id => 4, dirname => 'c', parent_id => 3],
     445        storage_object  => [so_id => 1, ext_id => $key1, ext_id_basename => basename($key1), dir_id => 4],
     446        directory       => [dir_id => 5, dirname => 'd', parent_id => 1],
     447        storage_object  => [so_id => 2, ext_id => $key2, ext_id_basename => basename($key2), dir_id => 5],
     448    );
     449}
     450
     451Test::Nebulous->setup;
     452
     453{
     454    my $key1 = "a/b/c/foo";
     455    my $key2 = "a/d/foo";
     456    $neb->create_object($key1);
     457    $neb->create_object($key2);
     458
     459    expected_dataset_ok(
     460        directory       => [dir_id => 1, dirname => '/', parent_id => 1],
     461        directory       => [dir_id => 2, dirname => 'a', parent_id => 1],
     462        directory       => [dir_id => 3, dirname => 'b', parent_id => 2],
     463        directory       => [dir_id => 4, dirname => 'c', parent_id => 3],
     464        storage_object  => [so_id => 1, ext_id => $key1, ext_id_basename => basename($key1), dir_id => 4],
     465        directory       => [dir_id => 5, dirname => 'd', parent_id => 2],
     466        storage_object  => [so_id => 2, ext_id => $key2, ext_id_basename => basename($key2), dir_id => 5],
     467    );
     468}
     469
     470Test::Nebulous->setup;
     471
     472{
     473    my $key1 = "a/b/c/foo";
     474    my $key2 = "d/a/foo";
     475    $neb->create_object($key1);
     476    $neb->create_object($key2);
     477
     478    expected_dataset_ok(
     479        directory       => [dir_id => 1, dirname => '/', parent_id => 1],
     480        directory       => [dir_id => 2, dirname => 'a', parent_id => 1],
     481        directory       => [dir_id => 3, dirname => 'b', parent_id => 2],
     482        directory       => [dir_id => 4, dirname => 'c', parent_id => 3],
     483        storage_object  => [so_id => 1, ext_id => $key1, ext_id_basename => basename($key1), dir_id => 4],
     484        directory       => [dir_id => 5, dirname => 'd', parent_id => 1],
     485        directory       => [dir_id => 6, dirname => 'a', parent_id => 5],
     486        storage_object  => [so_id => 2, ext_id => $key2, ext_id_basename => basename($key2), dir_id => 6],
     487    );
     488}
     489
     490Test::Nebulous->setup;
     491
     492{
     493    my $key1 = "a/b/c/foo";
     494    my $key2 = "a/b/c/d/foo";
     495    $neb->create_object($key1);
     496    $neb->create_object($key2);
     497
     498    expected_dataset_ok(
     499        directory       => [dir_id => 1, dirname => '/', parent_id => 1],
     500        directory       => [dir_id => 2, dirname => 'a', parent_id => 1],
     501        directory       => [dir_id => 3, dirname => 'b', parent_id => 2],
     502        directory       => [dir_id => 4, dirname => 'c', parent_id => 3],
     503        storage_object  => [so_id => 1, ext_id => $key1, ext_id_basename => basename($key1), dir_id => 4],
     504        directory       => [dir_id => 5, dirname => 'd', parent_id => 4],
     505        storage_object  => [so_id => 2, ext_id => $key2, ext_id_basename => basename($key2), dir_id => 5],
     506    );
     507}
     508
    336509Test::Nebulous->setup;
    337510
  • trunk/Nebulous-Server/t/08_server_delete_instance.t

    r20990 r23932  
    33# Copryight (C) 2004-2005  Joshua Hoblitt
    44#
    5 # $Id: 08_server_delete_instance.t,v 1.12 2008-12-14 22:54:25 eugene Exp $
     5# $Id: 08_server_delete_instance.t,v 1.10.22.1 2008-12-14 22:52:37 eugene Exp $
    66
    77use strict;
     
    2424
    2525{
    26     my $uri = $neb->create_object("foo");
     26    my $key = "foo";
     27    my $uri = $neb->create_object($key);
    2728
    28     ok($neb->delete_instance($uri), "delete instance");
     29    ok($neb->delete_instance($key, $uri), "delete instance");
    2930}
    3031
     
    3233
    3334{
    34     my $uri1 = $neb->create_object("foo");
    35     my $uri2 = $neb->replicate_object("foo");
     35    my $key = "foo";
     36    my $uri1 = $neb->create_object($key);
     37    my $uri2 = $neb->replicate_object($key);
    3638
    37     ok($neb->delete_instance($uri1), "delete instance");
     39    ok($neb->delete_instance($key, $uri1), "delete instance");
    3840
    39     my $locations = $neb->find_instances("foo");
     41    my $locations = $neb->find_instances($key);
    4042
    4143    is($locations->[0], $uri2, "instance remains");
    4244
    43     ok($neb->delete_instance( $uri2 ), "delete instance");
     45    ok($neb->delete_instance($key, $uri2), "delete instance");
    4446
    4547    eval {
    46         $neb->find_instances("foo");
     48        $neb->find_instances($key);
    4749    };
    4850    like($@, qr/is valid object key/, "storage object was deleted");
     
    5254
    5355eval {
    54     $neb->delete_instance("file:/foo");
     56    my $key = "foo";
     57    my $uri1 = $neb->create_object($key);
     58
     59    $neb->delete_instance($key, "file:/foo");
    5560};
    5661like($@, qr/no instance is associated with uri/, "uri does not exist");
     
    6166    $neb->delete_instance();
    6267};
    63 like($@, qr/1 was expected/, "no params");
     68like($@, qr/2 were expected/, "no params");
    6469
    6570Test::Nebulous->setup;
    6671
    6772eval {
    68     $neb->delete_instance("foo", 2);
     73    my $key = "foo";
     74    my $uri1 = $neb->create_object($key);
     75
     76    $neb->delete_instance("foo", 2, 3);
    6977};
    70 like($@, qr/1 was expected/, "too many params");
     78like($@, qr/2 were expected/, "too many params");
    7179
    7280Test::Nebulous->cleanup;
  • trunk/Nebulous-Server/t/10_server_is_valid_volume_name.t

    r20990 r23932  
    2323Test::Nebulous->setup;
    2424
    25 ok($neb->_is_valid_volume_name('node01'), "valid volume name");
     25ok($neb->_is_valid_volume_name('foo', 'node01'), "valid volume name");
    2626
    2727Test::Nebulous->setup;
    2828
    29 ok($neb->_is_valid_volume_name('node02'), "valid volume name");
     29ok($neb->_is_valid_volume_name('foo', 'node02'), "valid volume name");
    3030
    3131Test::Nebulous->setup;
    3232
    33 is($neb->_is_valid_volume_name('node99'), undef, "invalid volume name");
     33is($neb->_is_valid_volume_name('foo', 'node99'), undef, "invalid volume name");
    3434
    3535Test::Nebulous->cleanup;
  • trunk/Nebulous-Server/t/12_server_find_objects.t

    r17717 r23932  
    88use warnings FATAL => qw( all );
    99
    10 use Test::More tests => 6;
     10use Test::More tests => 28;
    1111
    1212use lib qw( ./t ./lib );
     
    2525# search for a regex of '' should match nothing
    2626eval {
    27     # key
    28     my $uri = $neb->create_object("foo");
     27    $neb->create_object("foo");
    2928
    3029    my $keys = $neb->find_objects();
     
    3534
    3635{
    37     # key
    38     my $uri = $neb->create_object("foo");
     36    $neb->create_object("foo");
    3937
    4038    my $keys = $neb->find_objects("foo");
     
    4846{
    4947    # key
    50     my $uri1 = $neb->create_object("foo");
    51     my $uri2 = $neb->replicate_object("foo");
     48    $neb->create_object("foo");
     49    $neb->replicate_object("foo");
    5250
    5351    my $keys = $neb->find_objects("foo");
     
    5553    is(scalar @$keys, 1, 'number of keys found');
    5654    is($keys->[0], "foo", "key name");
     55}
     56
     57Test::Nebulous->setup;
     58
     59{
     60    # key
     61    $neb->create_object("foo");
     62    $neb->create_object("bar");
     63
     64    my $keys = $neb->find_objects("foo");
     65
     66    is(scalar @$keys, 1, 'number of keys found');
     67    is($keys->[0], "foo", "key name");
     68}
     69
     70# test recursive dir searching
     71Test::Nebulous->setup;
     72
     73{
     74    $neb->create_object("a/foo");
     75
     76    my $keys = $neb->find_objects("a");
     77
     78    is(scalar @$keys, 1, 'number of keys found');
     79    is($keys->[0], "a/foo", "key name");
     80}
     81
     82Test::Nebulous->setup;
     83
     84{
     85    $neb->create_object("a/foo");
     86    $neb->create_object("b/foo");
     87
     88    my $keys = $neb->find_objects("a");
     89
     90    is(scalar @$keys, 1, 'number of keys found');
     91    is($keys->[0], "a/foo", "key name");
     92}
     93
     94Test::Nebulous->setup;
     95
     96{
     97    $neb->create_object("a/foo");
     98    $neb->create_object("a/b/foo");
     99
     100    my $keys = $neb->find_objects("a");
     101
     102    is(scalar @$keys, 1, 'number of keys found');
     103    is($keys->[0], "a/foo", "key name");
     104}
     105
     106Test::Nebulous->setup;
     107
     108{
     109    $neb->create_object("a/foo");
     110    $neb->create_object("a/bar");
     111
     112    my $keys = $neb->find_objects("a");
     113
     114    is(scalar @$keys, 2, 'number of keys found');
     115    is($keys->[0], "a/foo", "key name");
     116    is($keys->[1], "a/bar", "key name");
     117}
     118
     119Test::Nebulous->setup;
     120
     121{
     122    $neb->create_object("a/foo");
     123    $neb->create_object("bar");
     124
     125    my $keys = $neb->find_objects("a");
     126
     127    is(scalar @$keys, 1, 'number of keys found');
     128    is($keys->[0], "a/foo", "key name");
     129}
     130
     131Test::Nebulous->setup;
     132
     133{
     134    $neb->create_object("a/foo");
     135    $neb->create_object("foo");
     136    $neb->create_object("bar");
     137
     138    my $keys = $neb->find_objects("/");
     139
     140    is(scalar @$keys, 2, 'number of keys found');
     141    is($keys->[0], "foo", "key name");
     142    is($keys->[1], "bar", "key name");
     143}
     144
     145Test::Nebulous->setup;
     146
     147{
     148    $neb->create_object("a/foo");
     149    $neb->create_object("foo");
     150    $neb->create_object("bar");
     151
     152    my $keys = $neb->find_objects(".");
     153
     154    is(scalar @$keys, 2, 'number of keys found');
     155    is($keys->[0], "foo", "key name");
     156    is($keys->[1], "bar", "key name");
     157}
     158
     159Test::Nebulous->setup;
     160
     161{
     162    $neb->create_object("a/foo");
     163    $neb->create_object("foo");
     164    $neb->create_object("bar");
     165
     166    my $keys = $neb->find_objects("..");
     167
     168    is(scalar @$keys, 2, 'number of keys found');
     169    is($keys->[0], "foo", "key name");
     170    is($keys->[1], "bar", "key name");
    57171}
    58172
  • trunk/Nebulous-Server/t/13_server_rename_object.t

    r17717 r23932  
    88use warnings FATAL => qw( all );
    99
    10 use Test::More tests => 6;
     10use Test::More tests => 8;
    1111
    1212use lib qw( ./t ./lib );
    1313
     14use File::Basename qw( basename );
    1415use Nebulous::Server;
    1516use Test::Nebulous;
     
    2122);
    2223
     24use Test::DBUnit dsn => $NEB_DB, username => $NEB_USER, password => $NEB_PASS;
     25
    2326Test::Nebulous->setup;
    2427
    2528{
     29    my $key = "bar";
    2630    my $uri = $neb->create_object("foo");
    2731
    28     $neb->rename_object("foo", "bar");
     32    $neb->rename_object("foo", $key);
    2933
    30     eval {
    31         $neb->find_objects('^foo$');
    32     };
    33     like($@, qr/no keys found/, "old key name");
     34    expected_dataset_ok(
     35        directory       => [dir_id => 1, dirname => '/', parent_id => 1],
     36        storage_object  => [so_id => 1, ext_id => $key, ext_id_basename => basename($key), dir_id => 1],
     37    );
     38}
    3439
    35     my $keys = $neb->find_objects('^bar$');
    36     is(scalar @$keys, 1, 'number of keys found');
     40Test::Nebulous->setup;
     41
     42{
     43    my $key = "a/bar";
     44    my $uri = $neb->create_object("foo");
     45
     46    $neb->rename_object("foo", $key);
     47
     48    expected_dataset_ok(
     49        directory       => [dir_id => 1, dirname => '/', parent_id => 1],
     50        directory       => [dir_id => 2, dirname => 'a', parent_id => 1],
     51        storage_object  => [so_id => 1, ext_id => $key, ext_id_basename => basename($key), dir_id => 2],
     52    );
     53}
     54
     55Test::Nebulous->setup;
     56
     57{
     58    my $key = "bar";
     59    my $uri = $neb->create_object("a/foo");
     60
     61    $neb->rename_object("a/foo", $key);
     62
     63    expected_dataset_ok(
     64        directory       => [dir_id => 1, dirname => '/', parent_id => 1],
     65        directory       => [dir_id => 2, dirname => 'a', parent_id => 1],
     66        storage_object  => [so_id => 1, ext_id => $key, ext_id_basename => basename($key), dir_id => 1],
     67    );
    3768}
    3869
     
    73104like($@, qr/2 were expected/, "too many params");
    74105
     106# test attempting to rename a key in such a way to cause the distributed
     107# storage db to change
     108# this must be the last test as we're messing with the $neb object
     109eval {
     110    $neb->config->add_db(
     111        dbindex     => 1,
     112        dsn         => $NEB_DB,
     113        dbuser      => $NEB_USER,
     114        dbpasswd    => $NEB_PASS,
     115    );
     116
     117    $neb->create_object("a/foo");
     118    $neb->rename_object("a/foo", "g/bar");
     119};
     120like($@, qr/rename objects across distributed database boundaries/, "rename between databases");
     121
    75122Test::Nebulous->cleanup;
  • trunk/Nebulous-Server/t/16_server_swap_objects.t

    r20091 r23932  
    88use warnings FATAL => qw( all );
    99
    10 use Test::More tests => 8;
     10use Test::More tests => 13;
    1111
    1212use lib qw( ./t ./lib );
    1313
     14use File::Basename qw( basename );
    1415use Nebulous::Server;
    1516use Test::Nebulous;
     
    2122);
    2223
     24use Test::DBUnit dsn => $NEB_DB, username => $NEB_USER, password => $NEB_PASS;
     25
    2326Test::Nebulous->setup;
    2427
    2528{
    26     my $uri1 = $neb->create_object("foo1");
    27     my $uri2 = $neb->create_object("foo2");
     29    my $key1 = "foo1";
     30    my $key2 = "foo2";
     31    my $uri1 = $neb->create_object($key1);
     32    my $uri2 = $neb->create_object($key2);
    2833
    29     ok($neb->swap_objects("foo1", "foo2"), "swap succeeded");
     34    ok($neb->swap_objects($key1, $key2), "swap succeeded");
    3035
    31     my $new_uri1 = ($neb->find_instances("foo1"))->[0];
    32     my $new_uri2 = ($neb->find_instances("foo2"))->[0];
     36    my $new_uri1 = ($neb->find_instances($key1))->[0];
     37    my $new_uri2 = ($neb->find_instances($key2))->[0];
     38
     39    expected_dataset_ok(
     40        directory       => [dir_id => 1, dirname => '/', parent_id => 1],
     41        storage_object  => [so_id => 1, ext_id => $key2, ext_id_basename => basename($key2), dir_id => 1],
     42        storage_object  => [so_id => 2, ext_id => $key1, ext_id_basename => basename($key1), dir_id => 1],
     43    );
     44
     45    is($uri1, $new_uri2, "key1 -> key2");
     46    is($uri2, $new_uri1, "key2 -> key1");
     47}
     48
     49Test::Nebulous->setup;
     50
     51{
     52    my $key1 = "foo1";
     53    my $key2 = "a/foo2";
     54    my $uri1 = $neb->create_object($key1);
     55    my $uri2 = $neb->create_object($key2);
     56
     57    ok($neb->swap_objects($key1, $key2), "swap succeeded");
     58
     59    my $new_uri1 = ($neb->find_instances($key1))->[0];
     60    my $new_uri2 = ($neb->find_instances($key2))->[0];
     61
     62    expected_dataset_ok(
     63        directory       => [dir_id => 1, dirname => '/', parent_id => 1],
     64        directory       => [dir_id => 2, dirname => 'a', parent_id => 1],
     65        storage_object  => [so_id => 1, ext_id => $key2, ext_id_basename => basename($key2), dir_id => 2],
     66        storage_object  => [so_id => 2, ext_id => $key1, ext_id_basename => basename($key1), dir_id => 1],
     67    );
    3368
    3469    is($uri1, $new_uri2, "key1 -> key2");
  • trunk/Nebulous-Server/t/75_parse_neb_key.t

    r19431 r23932  
    1010use Test::More;
    1111
    12 plan tests => 80;
     12plan tests => 99;
    1313
    1414use lib qw( ./t ./lib );
    1515
    16 use Nebulous::Keys qw( parse_neb_key );
     16use Nebulous::Key qw( parse_neb_key );
    1717use Test::Nebulous;
    1818
     
    224224}
    225225
     226# root volume references
     227{
     228    my $key = parse_neb_key('neb:///');
     229
     230    is($key->path, '', 'path');
     231    is($key->volume, undef, 'volume name');
     232    is($key->soft_volume, undef, 'soft volume name');
     233}
     234
     235{
     236    my $key = parse_neb_key('neb:///.');
     237
     238    is($key->path, '', 'path');
     239    is($key->volume, undef, 'volume name');
     240    is($key->soft_volume, undef, 'soft volume name');
     241}
     242
     243{
     244    my $key = parse_neb_key('neb:///..');
     245
     246    is($key->path, '', 'path');
     247    is($key->volume, undef, 'volume name');
     248    is($key->soft_volume, undef, 'soft volume name');
     249}
     250
     251{
     252    my $key = parse_neb_key('/');
     253
     254    is($key->path, '', 'path');
     255    is($key->volume, undef, 'volume name');
     256    is($key->soft_volume, undef, 'soft volume name');
     257}
     258
     259{
     260    my $key = parse_neb_key('.');
     261
     262    is($key->path, '', 'path');
     263    is($key->volume, undef, 'volume name');
     264    is($key->soft_volume, undef, 'soft volume name');
     265}
     266
     267{
     268    my $key = parse_neb_key('..');
     269
     270    is($key->path, '', 'path');
     271    is($key->volume, undef, 'volume name');
     272    is($key->soft_volume, undef, 'soft volume name');
     273}
     274
    226275# key w/ whitespace
    227276eval {
     
    267316};
    268317like( $@, qr/requires a leading slash/, "leading slash" );
     318
     319# URI w/ volume but w/o path
     320eval {
     321    my $key = parse_neb_key('neb://foo');
     322};
     323like( $@, qr/requires a path/, "no path" );
Note: See TracChangeset for help on using the changeset viewer.