Changeset 23932 for trunk/Nebulous-Server
- Timestamp:
- Apr 20, 2009, 11:15:20 AM (17 years ago)
- Location:
- trunk/Nebulous-Server
- Files:
-
- 1 deleted
- 20 edited
- 2 copied
-
. (modified) (1 prop)
-
Build.PL (modified) (2 diffs)
-
Changes (modified) (1 diff)
-
MANIFEST (modified) (3 diffs)
-
bin/neb-admin (modified) (1 diff)
-
lib/Nebulous/Key.pm (copied) (copied from branches/neb_distrib_20081210/Nebulous-Server/lib/Nebulous/Key.pm )
-
lib/Nebulous/Keys.pm (deleted)
-
lib/Nebulous/Server.pm (modified) (46 diffs)
-
lib/Nebulous/Server.pod (modified) (2 diffs)
-
lib/Nebulous/Server/Config.pm (modified) (4 diffs)
-
lib/Nebulous/Server/Log.pm (modified) (2 diffs)
-
lib/Nebulous/Server/SOAP.pm (modified) (5 diffs)
-
lib/Nebulous/Server/SQL.pm (modified) (7 diffs)
-
t/01_load.t (modified) (1 diff)
-
t/02_config.t (copied) (copied from trunk/Nebulous-Server/t/02_config.t ) (1 diff)
-
t/02_server_setup.t (modified) (2 diffs)
-
t/03_server_create_object.t (modified) (3 diffs)
-
t/08_server_delete_instance.t (modified) (5 diffs)
-
t/10_server_is_valid_volume_name.t (modified) (1 diff)
-
t/12_server_find_objects.t (modified) (5 diffs)
-
t/13_server_rename_object.t (modified) (3 diffs)
-
t/16_server_swap_objects.t (modified) (2 diffs)
-
t/75_parse_neb_key.t (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Nebulous-Server
-
Property svn:mergeinfo
set to
/branches/neb_distrib_20081210/Nebulous-Server merged eligible /trunk/Nebulous-Server merged eligible
-
Property svn:mergeinfo
set to
-
trunk/Nebulous-Server/Build.PL
r23675 r23932 23 23 'File::Temp' => 0, 24 24 'Filesys::Df' => '0.92', 25 'Log::Dispatch::Email::MailSend' => 0, 25 26 'Log::Log4perl' => '0.48', 26 'Log::Dispatch::Email::MailSend' => 0,27 27 'Net::Server::Daemonize'=> '0.05', 28 28 'Params::Validate' => '0.73', … … 34 34 'Test::More' => '0.49', 35 35 'Test::URI' => '1.06', 36 'Test::DBUnit' => '0.20', 36 37 }, 37 38 recommends => { -
trunk/Nebulous-Server/Changes
r23698 r23932 8 8 - add email logging of events to nebdiskd 9 9 - 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 10 18 11 19 0.16 -
trunk/Nebulous-Server/MANIFEST
r23340 r23932 4 4 MANIFEST 5 5 README 6 Todo7 6 bin/neb-admin 8 7 bin/neb-fsck … … 19 18 examples/uri_test.pl 20 19 init.d/nebdiskd 21 lib/Nebulous/Key s.pm20 lib/Nebulous/Key.pm 22 21 lib/Nebulous/Server.pm 23 22 lib/Nebulous/Server.pod … … 33 32 t/00_distribution.t 34 33 t/01_load.t 34 t/02_config.t 35 35 t/02_server_setup.t 36 36 t/03_server_create_object.t -
trunk/Nebulous-Server/bin/neb-admin
r23560 r23932 174 174 # if the copies xattr is unset and the object has 2 or more instances, we 175 175 # 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. 176 180 my $copies = $obj->{copies} || 2; 177 181 -
trunk/Nebulous-Server/lib/Nebulous/Server.pm
r23698 r23932 9 9 no warnings qw( uninitialized ); 10 10 11 our $VERSION = '0.1 5';11 our $VERSION = '0.17'; 12 12 13 13 use base qw( Class::Accessor::Fast ); … … 15 15 use DBI; 16 16 use Digest::SHA1 qw( sha1_hex ); 17 use File::Basename qw( dirname );17 use File::Basename qw( basename dirname fileparse ); 18 18 use File::ExtAttr qw( setfattr ); 19 19 use File::Path; 20 20 use File::Spec; 21 use Log::Log4perl ;22 use Nebulous::Key sqw( parse_neb_key parse_neb_volume );21 use Log::Log4perl qw( :levels ); 22 use Nebulous::Key qw( parse_neb_key parse_neb_volume ); 23 23 use Nebulous::Server::Config; 24 24 use Nebulous::Server::Log; 25 25 use Nebulous::Server::SQL; 26 use Params::Validate qw( validate _pos SCALAR SCALARREF UNDEF);26 use Params::Validate qw( validate validate_pos SCALAR SCALARREF UNDEF BOOLEAN ); 27 27 use URI::file; 28 28 … … 37 37 38 38 # 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 45 sub new_from_config 46 { 47 my ($class, $config) = @_; 40 48 41 49 # log4perl is not avaliable until we call init() 42 50 Nebulous::Server::Log->init($config); 43 51 my $log = Log::Log4perl::get_logger( "Nebulous::Server" ); 52 $log->level($config->trace); 44 53 45 54 my $sql = Nebulous::Server::SQL->new; … … 52 61 $self->config($config); 53 62 54 # ask for the db handle as a means of validating the database parameters55 $self->db;56 57 63 $log->debug( "leaving" ); 58 64 59 65 return $self; 60 66 } 61 67 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 70 sub _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 90 sub _db_for_index 91 { 92 my ($self, $db_index) = @_; 71 93 72 94 my $log = $self->log; … … 74 96 my $config = $self->config; 75 97 98 # lookup to see if we have a stored dbh for this database 99 my $dbh = $self->{dbs}[$db_index]; 76 100 # if the dbh is still alive, return it 77 if (defined $ self->{db} and $self->{db}->ping) {101 if (defined $dbh and $dbh->ping) { 78 102 $log->debug("db handle is still alive"); 79 return $ self->{db};103 return $dbh; 80 104 } 81 105 # otherwise create a new connection 82 106 $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; 83 112 84 113 # if we're running under mod_perl & Apache::DBI is loaded we want to … … 87 116 # processes and the database might have gone away on us. Apache::DBI will 88 117 # take care of getting a valid dbh back. 89 my $db;90 118 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, 95 123 { 96 124 RaiseError => 1, … … 100 128 ); 101 129 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; 105 133 $log->debug("commit"); 106 134 }; 107 135 if ( $@ ) { 108 $db ->rollback if $db;136 $dbh->rollback if $dbh; 109 137 $log->debug("rollback"); 110 138 $log->logdie( "database error: $@" ); 111 139 } 112 140 113 $self->{db} = $db; 114 115 return $db; 116 } 117 141 $self->{dbs}[$db_index] = $dbh; 142 143 return $dbh; 144 } 145 146 sub 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 } 118 166 119 167 sub create_object … … 138 186 ); 139 187 140 my $log = $self->log;141 my $sql = $self->sql;142 my $db =$self->db;143 144 $log->debug( "entered - @_" );145 146 188 # vol_name overrides the key implied volume 147 189 $key = parse_neb_key($key, $vol_name); 148 190 $vol_name = $key->volume; 149 191 192 my $log = $self->log; 193 my $sql = $self->sql; 194 my $db = $self->db($key); 195 196 $log->debug( "entered - @_" ); 197 150 198 # the key's volume can't be validiated on input for this method so we have 151 199 # to check it after parsing the key 152 200 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)) { 154 202 if ($key->soft_volume) { 155 203 $log->warn( "$vol_name is not a known volume name" ); … … 161 209 162 210 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); 164 214 165 215 my $uri; … … 169 219 # create storage_object 170 220 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); 172 222 } 173 223 … … 215 265 216 266 # 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); 218 268 $log->debug("created $uri on volume ID: $vol_id"); 219 269 … … 247 297 248 298 299 sub _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; 352 TRANS: 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 249 420 sub rename_object 250 421 { … … 266 437 }, 267 438 ); 268 269 my $log = $self->log;270 my $sql = $self->sql;271 my $db =$self->db;272 273 $log->debug("entered - @_");274 439 275 440 # ignore volumes 276 441 $key = parse_neb_key($key); 277 442 $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 } 278 455 279 456 TRANS: while (1) { … … 282 459 my $query = $db->prepare_cached($sql->rename_object); 283 460 # 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); 285 462 286 463 # if we affected more then one row something very bad has happened. … … 310 487 } 311 488 312 313 489 sub swap_objects 314 490 { … … 329 505 }, 330 506 ); 331 332 my $log = $self->log;333 my $sql = $self->sql;334 my $db =$self->db;335 336 $log->debug("entered - @_");337 507 338 508 # ignore volumes … … 340 510 $key2 = parse_neb_key($key2); 341 511 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: 343 526 # key1 -> key1.swap 344 527 # key2 -> key1 345 528 # key1.swap -> key2 346 529 347 TRANS: while (1) { 530 my $db = $dbh1; 531 TRANS: while (1) { 348 532 eval { 349 533 { 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 } 387 574 388 575 $db->commit; … … 398 585 $log->logdie("database error: $@"); 399 586 } 400 last;401 }587 last; 588 } 402 589 403 590 $log->debug("leaving"); … … 406 593 } 407 594 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 408 609 409 610 sub replicate_object … … 440 641 # then we should throw an error 441 642 442 my $log = $self->log;443 my $sql = $self->sql;444 my $db =$self->db;445 446 $log->debug("entered - @_");447 448 643 # vol_name overrides the key implied volume 449 644 $key = parse_neb_key($key, $vol_name); 450 645 $vol_name = $key->volume; 451 646 647 my $log = $self->log; 648 my $sql = $self->sql; 649 my $db = $self->db($key); 650 651 $log->debug("entered - @_"); 652 452 653 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)) { 454 655 if ($key->soft_volume) { 455 656 $log->warn( "$vol_name is not a known volume name" ); … … 463 664 if (defined $vol_name) { 464 665 ($vol_id, $vol_host, $vol_path, $vol_xattr) 465 = $self->_get_storage_volume($ vol_name);666 = $self->_get_storage_volume($key, $vol_name); 466 667 } else { 467 668 ($vol_id, $vol_host, $vol_path, $vol_xattr) … … 508 709 509 710 # 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); 511 714 512 715 { … … 561 764 ); 562 765 563 my $log = $self->log;564 my $sql = $self->sql;565 my $db =$self->db;566 567 $log->debug( "entered - @_" );568 569 766 # ignore volume 570 767 $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 - @_" ); 571 774 572 775 my $so_id; … … 671 874 ); 672 875 673 my $log = $self->log;674 my $sql = $self->sql;675 my $db =$self->db;676 677 $log->debug( "entered - @_" );678 679 876 # ignore volume 680 877 $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 - @_" ); 681 884 682 885 my $so_id; … … 790 993 ); 791 994 792 my $log = $self->log;793 my $sql = $self->sql;794 my $db =$self->db;795 796 $log->debug("entered - @_");797 798 995 # ignore volume 799 996 $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 - @_"); 800 1003 801 1004 TRANS: while (1) { … … 864 1067 ); 865 1068 866 my $log = $self->log;867 my $sql = $self->sql;868 my $db =$self->db;869 870 $log->debug("entered - @_");871 872 1069 # ignore volume 873 1070 $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 - @_"); 874 1077 875 1078 my $value; … … 917 1120 ); 918 1121 919 my $log = $self->log;920 my $sql = $self->sql;921 my $db =$self->db;922 923 $log->debug("entered - @_");924 925 1122 # ignore volume 926 1123 $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 - @_"); 927 1130 928 1131 my @xattrs; … … 960 1163 ); 961 1164 962 my $log = $self->log;963 my $sql = $self->sql;964 my $db =$self->db;965 966 $log->debug("entered - @_");967 968 1165 # ignore volume 969 1166 $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 - @_"); 970 1173 971 1174 TRANS: while (1) { … … 1001 1204 } 1002 1205 1003 1206 # loop over all db_index values, passing db_index to each call 1004 1207 sub find_objects 1005 1208 { 1006 1209 my $self = shift; 1007 1210 1008 my ( $pattern) = validate_pos( @_,1211 my ($pattern) = validate_pos( @_, 1009 1212 { 1010 1213 type => SCALAR, … … 1013 1216 ); 1014 1217 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; 1018 1221 1019 1222 $log->debug( "entered - @_" ); 1020 1223 1021 unless ( $pattern) {1224 unless (defined $pattern) { 1022 1225 $log->debug( "leaving" ); 1023 1226 $log->logdie("no keys found"); 1024 1227 } 1025 1228 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 1243 sub _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 1029 1257 my @keys; 1030 1258 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 ); 1033 1293 1034 1294 while ( my $row = $query->fetchrow_hashref ) { 1035 1295 my $key = $row->{ 'ext_id' }; 1036 1296 push @keys, $key if $key; 1297 $log->debug( "matched $key" ) if $key; 1037 1298 } 1038 1299 }; 1039 1300 $log->logdie("database error: $@") if $@; 1040 1041 $log->logdie("no keys found") unless ( scalar @keys );1042 1301 1043 1302 $log->debug( "leaving" ); … … 1071 1330 ); 1072 1331 1073 my $log = $self->log;1074 my $sql = $self->sql;1075 my $db =$self->db;1076 1077 $log->debug("entered - @_");1078 1079 1332 # vol_name overrides the key implied volume 1080 1333 $key = parse_neb_key($key, $vol_name); 1081 1334 $vol_name = $key->volume; 1082 1335 1336 my $log = $self->log; 1337 my $sql = $self->sql; 1338 my $db = $self->db($key); 1339 1340 $log->debug("entered - @_"); 1341 1083 1342 # the key's volume can't be validiated on input for this method so we have 1084 1343 # to check it after parsing the key 1085 1344 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)) { 1087 1346 if ($key->soft_volume) { 1088 1347 $log->warn( "$vol_name is not a known volume name" ); … … 1144 1403 my $self = shift; 1145 1404 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 }, 1147 1412 { 1148 1413 type => SCALAR|SCALARREF, … … 1150 1415 ); 1151 1416 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); 1155 1423 1156 1424 $log->debug( "entered - @_" ); … … 1244 1512 ); 1245 1513 1246 my $log = $self->log;1247 my $sql = $self->sql;1248 my $db =$self->db;1249 1250 $log->debug("entered - @_");1251 1252 1514 # ignore volume 1253 1515 $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 - @_"); 1254 1522 1255 1523 my $stat; … … 1272 1540 } 1273 1541 1274 1542 # this should have a 'db_index' as an argument 1275 1543 sub mounts 1276 1544 { 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 1277 1548 my $self = shift; 1278 1549 … … 1281 1552 my $log = $self->log; 1282 1553 my $sql = $self->sql; 1283 my $db = $self->db;1554 my $db = $self->_db_for_index(0); # XXX fix as above 1284 1555 1285 1556 $log->debug("entered - @_"); … … 1310 1581 my $self = shift; 1311 1582 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); 1315 1588 1316 1589 no warnings qw( uninitialized ); 1317 1590 $log->debug( "entered - @_" ); 1318 1591 use warnings; 1319 1320 my ($name, $soft_volume) = @_;1321 1592 1322 1593 my ($vol_id, $vol_host, $vol_path, $xattr); … … 1335 1606 # find it, fall back to any volume 1336 1607 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); 1338 1609 return; # this just returns out of the eval not from the subroutine 1339 1610 } … … 1375 1646 my $self = shift; 1376 1647 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); 1380 1653 1381 1654 no warnings qw( uninitialized ); 1382 1655 $log->debug( "entered - @_" ); 1383 1656 use warnings; 1384 1385 my $key = shift;1386 1387 $key = parse_neb_key($key);1388 1657 1389 1658 my ($vol_id, $vol_host, $vol_path, $xattr); … … 1423 1692 my ($self, $key) = @_; 1424 1693 1425 my $log = $self->log;1426 my $sql = $self->sql;1427 my $db =$self->db;1428 1429 1694 $key = parse_neb_key($key); 1695 1696 my $log = $self->log; 1697 my $sql = $self->sql; 1698 my $db = $self->db($key); 1430 1699 1431 1700 my $ext_id; … … 1452 1721 sub _is_valid_volume_name 1453 1722 { 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); 1460 1726 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); 1461 1731 1462 1732 $vol_name = $volume_info->{volume}; … … 1493 1763 my $log = $self->log; 1494 1764 my $sql = $self->sql; 1495 my $db = $self->db ;1765 my $db = $self->db($key); 1496 1766 1497 1767 my $uri; 1498 1768 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); 1501 1771 unless (-d $storage_path) { 1502 1772 _retry(sub { mkpath(@_) }, $storage_path, 0, 0775) … … 1507 1777 my $mode = [_retry(sub { stat($storage_path) } )]->[2] & 07777; 1508 1778 unless ($mode == 0775) { 1509 $log->error("$storage_path has the wrong permissions of: %04 o", $mode);1779 $log->error("$storage_path has the wrong permissions of: %04x", $mode); 1510 1780 _retry(sub { chmod(0775, $storage_path) }) or die "can't chmod $storage_path: $!"; 1511 1781 } … … 1523 1793 my $path = $uri->file; 1524 1794 die "can not set xattr on $path: $!" 1525 unless (setfattr($path, 'user.nebulous_key', $key ));1795 unless (setfattr($path, 'user.nebulous_key', $key->path)); 1526 1796 } 1527 1797 … … 1579 1849 1580 1850 my ($key, $vol_path) = @_; 1581 1582 # if the key has '/' in it, hash only the dirname() component1583 if ($key =~ m|/|) {1584 $key = dirname($key);1585 }1586 1851 1587 1852 # taken and modified from Cache::File::cache_file_path() … … 1627 1892 my $log = $self->log; 1628 1893 my $sql = $self->sql; 1629 my $db =$self->db;1894 # my $db = $self->db; 1630 1895 1631 1896 $log->debug( "entered" ); 1632 1897 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; } ); 1636 1902 1637 1903 $log->debug( "leaving" ); -
trunk/Nebulous-Server/lib/Nebulous/Server.pod
r20092 r23932 26 26 Nebulous::Server->find_objects( $pattern ); 27 27 Nebulous::Server->find_instances( $key, $volume ); 28 Nebulous::Server->delete_instance( $ uri );28 Nebulous::Server->delete_instance( $key, $uri ); 29 29 Nebulous::Server->stat_object( $key ); 30 30 Nebulous::Server->mounts(); … … 160 160 Throws an exception on error. 161 161 162 =item * delete_instance( $ uri );163 164 Accepts 1 parameters, it is mandatory. Returns Boolean true. Throws an165 exception on error.162 =item * delete_instance( $key, $uri ); 163 164 Accepts 2 parameters, both mandatory. Returns Boolean true. C<<$uri>> must be 165 an instance of C<<$key>>. Throws an exception on error. 166 166 167 167 =item * swap_objects( $key1, $key2 ); -
trunk/Nebulous-Server/lib/Nebulous/Server/Config.pm
r20990 r23932 8 8 use warnings FATAL => qw( all ); 9 9 10 our $VERSION = 0.0 2;10 our $VERSION = 0.03; 11 11 12 12 use base qw( Class::Accessor::Fast ); 13 13 14 14 use Log::Log4perl qw( :levels ); 15 use Params::Validate qw( validate SCALAR );15 use Params::Validate qw( validate validate_pos SCALAR ); 16 16 17 17 our %LEVELS = ( … … 25 25 ); 26 26 27 my $new_validate = { 27 my $db_validate = { 28 dbindex => { 29 type => SCALAR, 30 regex => qr/^\d+$/, 31 }, 28 32 dsn => { type => SCALAR }, 29 33 dbuser => { type => SCALAR }, 30 34 dbpasswd => { type => SCALAR }, 31 log_level => { 35 }; 36 37 my $new_validate = { 38 trace => { 32 39 type => SCALAR, 33 40 optional => 1, 34 default => ' all',41 default => 'fatal', 35 42 callbacks => { 36 43 'is valid level' => sub { … … 39 46 }, 40 47 }, 48 dsn => { type => SCALAR, optional => 1 }, 49 dbuser => { type => SCALAR, optional => 1 }, 50 dbpasswd => { type => SCALAR, optional => 1 }, 41 51 }; 42 52 43 53 __PACKAGE__->mk_ro_accessors( keys %$new_validate ); 44 54 45 sub init { 55 56 sub new 57 { 46 58 my $class = shift; 47 59 … … 49 61 50 62 # 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})} }; 54 64 55 65 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 } 56 78 57 79 return $self; 58 80 } 59 81 82 83 sub 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 101 sub 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 114 sub n_db 115 { 116 my $self = shift; 117 118 return scalar @{ $self->{dbs} }; 119 } 120 121 122 package Nebulous::Server::Config::DB; 123 124 use strict; 125 use warnings FATAL => qw( all ); 126 127 our $VERSION = 0.01; 128 129 use base qw( Class::Accessor::Fast ); 130 131 __PACKAGE__->mk_ro_accessors(qw( dsn dbuser dbpasswd )); 132 60 133 1; 61 134 -
trunk/Nebulous-Server/lib/Nebulous/Server/Log.pm
r20990 r23932 16 16 my ($self, $config) = @_; 17 17 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; 21 21 22 22 my $conf = <<END; … … 30 30 # date | hostname | priority | method/sub - message\n 31 31 32 log4perl.appender.SQLLOG = Log::Log4perl::Appender::DBI33 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 = 37 37 INSERT INTO log (timestamp, hostname, level, sub, message) \ 38 38 VALUES (%d, %H, %p, %M, %m) -
trunk/Nebulous-Server/lib/Nebulous/Server/SOAP.pm
r20990 r23932 1 1 # Copyright (c) 2004 Joshua Hoblitt 2 2 # 3 # $Id: SOAP.pm,v 1. 6 2008-12-14 22:54:25eugene Exp $3 # $Id: SOAP.pm,v 1.4.32.1 2008-12-14 22:52:37 eugene Exp $ 4 4 5 5 package Nebulous::Server::SOAP; … … 17 17 our $AUTOLOAD; 18 18 19 our @args;19 our $config; 20 20 our $neb; 21 21 22 sub new_on_init { 22 23 sub new_on_init 24 { 23 25 my $self = shift; 24 26 … … 27 29 require Apache2::ServerUtil; 28 30 29 @args = @_;31 $config = shift; 30 32 31 33 my $s = Apache2::ServerUtil->server; … … 35 37 } 36 38 37 sub init { 39 40 sub init 41 { 38 42 my $self = shift; 39 43 40 $neb = Nebulous::Server->new (@args);44 $neb = Nebulous::Server->new_from_config($config); 41 45 42 46 return Apache2::Const::OK; 43 47 } 44 48 45 sub AUTOLOAD { 49 50 sub AUTOLOAD 51 { 46 52 my $self = shift; 47 53 … … 76 82 } 77 83 84 78 85 1; -
trunk/Nebulous-Server/lib/Nebulous/Server/SQL.pm
r23699 r23932 8 8 use warnings FATAL => qw( all ); 9 9 10 our $VERSION = '0.0 2';10 our $VERSION = '0.04'; 11 11 12 12 use base qw( Class::Accessor::Fast ); … … 26 26 new_object => qq{ 27 27 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', ?) 30 30 }, 31 31 new_object_attr => qq{ … … 60 60 USING (so_id) 61 61 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 (?, ?) 62 74 }, 63 75 check_object_name => qq{ … … 297 309 USING(vol_id) 298 310 }, 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 = ? 303 320 }, 304 321 rename_object => qq{ 305 322 UPDATE storage_object 306 SET ext_id = ? 323 SET ext_id = ?, ext_id_basename = ?, dir_id = ? 307 324 WHERE ext_id = ? 308 325 }, … … 330 347 GROUP BY so_id 331 348 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; 332 372 }, 333 373 find_objects_with_extra_instances => qq{ … … 387 427 DROP TABLE IF EXISTS log; 388 428 DROP TABLE IF EXISTS mountedvol; 429 DROP TABLE IF EXISTS directory; 389 430 DROP PROCEDURE IF EXISTS getmountedvol; 390 431 SET FOREIGN_KEY_CHECKS=1 … … 408 449 409 450 __DATA__ 451 CREATE 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 462 INSERT INTO directory (dir_id, dirname, parent_id) VALUES (1, '/', 1); 463 464 ### 465 410 466 CREATE TABLE storage_object ( 411 467 so_id BIGINT NOT NULL AUTO_INCREMENT, 412 468 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), 413 472 type enum('REG_FILE'), 414 473 PRIMARY KEY(so_id), -
trunk/Nebulous-Server/t/01_load.t
r17076 r23932 12 12 use Test::More tests => 5; 13 13 14 BEGIN { use_ok( 'Nebulous::Key s' ); }14 BEGIN { use_ok( 'Nebulous::Key' ); } 15 15 BEGIN { use_ok( 'Nebulous::Server' ); } 16 16 BEGIN { use_ok( 'Nebulous::Server::Log' ); } -
trunk/Nebulous-Server/t/02_config.t
r23931 r23932 3 3 # Copryight (C) 2004-2005 Joshua Hoblitt 4 4 # 5 # $Id: 02_config.t,v 1.1 2008-12-12 21:13:41 jhoblittExp $5 # $Id: 02_config.t,v 1.1.2.2 2008-12-14 22:52:37 eugene Exp $ 6 6 7 7 use strict; -
trunk/Nebulous-Server/t/02_server_setup.t
r20990 r23932 8 8 use warnings; 9 9 10 use Test::More tests => 2;10 use Test::More tests => 6; 11 11 12 12 use lib qw( ./t ./lib ); … … 17 17 Test::Nebulous->setup; 18 18 19 isa_ok( 20 Nebulous::Server->new( 21 dsn => $NEB_DB, 22 dbuser => $NEB_USER, 23 dbpasswd => $NEB_PASS, 24 ), 25 "Nebulous::Server" 26 ); 19 isa_ok(Nebulous::Server->new(), "Nebulous::Server"); 27 20 28 21 Test::Nebulous->setup; 29 22 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 30 Test::Nebulous->setup; 31 32 { 33 my $neb = Nebulous::Server->new( 32 34 dsn => "DBI:mysql:database=foobar:host=localhost", 33 35 dbuser => "baz", 34 36 dbpasswd =>"boo", 35 37 ); 36 }; 37 like( $@, qr/DBI connect.*? failed/, "bad dsn/user/pass" ); 38 39 ok($neb, "set database"); 40 } 41 42 Test::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 } 38 64 39 65 Test::Nebulous->cleanup; -
trunk/Nebulous-Server/t/03_server_create_object.t
r19493 r23932 8 8 use warnings FATAL => qw( all ); 9 9 10 use Test::More tests => 89;10 use Test::More tests => 99; 11 11 12 12 use lib qw( ./t ./lib ); 13 13 14 use File::Basename qw( basename ); 14 15 use File::ExtAttr qw( getfattr ); 15 16 use Nebulous::Server; … … 26 27 ); 27 28 29 use Test::DBUnit dsn => $NEB_DB, username => $NEB_USER, password => $NEB_PASS; 30 28 31 Test::Nebulous->setup; 29 32 … … 334 337 } 335 338 339 # test for properly row creation in the directories table 340 341 Test::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 353 Test::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 367 Test::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 381 Test::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 396 Test::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 414 Test::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 432 Test::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 451 Test::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 470 Test::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 490 Test::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 336 509 Test::Nebulous->setup; 337 510 -
trunk/Nebulous-Server/t/08_server_delete_instance.t
r20990 r23932 3 3 # Copryight (C) 2004-2005 Joshua Hoblitt 4 4 # 5 # $Id: 08_server_delete_instance.t,v 1.1 2 2008-12-14 22:54:25eugene Exp $5 # $Id: 08_server_delete_instance.t,v 1.10.22.1 2008-12-14 22:52:37 eugene Exp $ 6 6 7 7 use strict; … … 24 24 25 25 { 26 my $uri = $neb->create_object("foo"); 26 my $key = "foo"; 27 my $uri = $neb->create_object($key); 27 28 28 ok($neb->delete_instance($ uri), "delete instance");29 ok($neb->delete_instance($key, $uri), "delete instance"); 29 30 } 30 31 … … 32 33 33 34 { 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); 36 38 37 ok($neb->delete_instance($ uri1), "delete instance");39 ok($neb->delete_instance($key, $uri1), "delete instance"); 38 40 39 my $locations = $neb->find_instances( "foo");41 my $locations = $neb->find_instances($key); 40 42 41 43 is($locations->[0], $uri2, "instance remains"); 42 44 43 ok($neb->delete_instance( $uri2), "delete instance");45 ok($neb->delete_instance($key, $uri2), "delete instance"); 44 46 45 47 eval { 46 $neb->find_instances( "foo");48 $neb->find_instances($key); 47 49 }; 48 50 like($@, qr/is valid object key/, "storage object was deleted"); … … 52 54 53 55 eval { 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"); 55 60 }; 56 61 like($@, qr/no instance is associated with uri/, "uri does not exist"); … … 61 66 $neb->delete_instance(); 62 67 }; 63 like($@, qr/ 1 wasexpected/, "no params");68 like($@, qr/2 were expected/, "no params"); 64 69 65 70 Test::Nebulous->setup; 66 71 67 72 eval { 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); 69 77 }; 70 like($@, qr/ 1 wasexpected/, "too many params");78 like($@, qr/2 were expected/, "too many params"); 71 79 72 80 Test::Nebulous->cleanup; -
trunk/Nebulous-Server/t/10_server_is_valid_volume_name.t
r20990 r23932 23 23 Test::Nebulous->setup; 24 24 25 ok($neb->_is_valid_volume_name(' node01'), "valid volume name");25 ok($neb->_is_valid_volume_name('foo', 'node01'), "valid volume name"); 26 26 27 27 Test::Nebulous->setup; 28 28 29 ok($neb->_is_valid_volume_name(' node02'), "valid volume name");29 ok($neb->_is_valid_volume_name('foo', 'node02'), "valid volume name"); 30 30 31 31 Test::Nebulous->setup; 32 32 33 is($neb->_is_valid_volume_name(' node99'), undef, "invalid volume name");33 is($neb->_is_valid_volume_name('foo', 'node99'), undef, "invalid volume name"); 34 34 35 35 Test::Nebulous->cleanup; -
trunk/Nebulous-Server/t/12_server_find_objects.t
r17717 r23932 8 8 use warnings FATAL => qw( all ); 9 9 10 use Test::More tests => 6;10 use Test::More tests => 28; 11 11 12 12 use lib qw( ./t ./lib ); … … 25 25 # search for a regex of '' should match nothing 26 26 eval { 27 # key 28 my $uri = $neb->create_object("foo"); 27 $neb->create_object("foo"); 29 28 30 29 my $keys = $neb->find_objects(); … … 35 34 36 35 { 37 # key 38 my $uri = $neb->create_object("foo"); 36 $neb->create_object("foo"); 39 37 40 38 my $keys = $neb->find_objects("foo"); … … 48 46 { 49 47 # 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"); 52 50 53 51 my $keys = $neb->find_objects("foo"); … … 55 53 is(scalar @$keys, 1, 'number of keys found'); 56 54 is($keys->[0], "foo", "key name"); 55 } 56 57 Test::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 71 Test::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 82 Test::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 94 Test::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 106 Test::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 119 Test::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 131 Test::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 145 Test::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 159 Test::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"); 57 171 } 58 172 -
trunk/Nebulous-Server/t/13_server_rename_object.t
r17717 r23932 8 8 use warnings FATAL => qw( all ); 9 9 10 use Test::More tests => 6;10 use Test::More tests => 8; 11 11 12 12 use lib qw( ./t ./lib ); 13 13 14 use File::Basename qw( basename ); 14 15 use Nebulous::Server; 15 16 use Test::Nebulous; … … 21 22 ); 22 23 24 use Test::DBUnit dsn => $NEB_DB, username => $NEB_USER, password => $NEB_PASS; 25 23 26 Test::Nebulous->setup; 24 27 25 28 { 29 my $key = "bar"; 26 30 my $uri = $neb->create_object("foo"); 27 31 28 $neb->rename_object("foo", "bar");32 $neb->rename_object("foo", $key); 29 33 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 } 34 39 35 my $keys = $neb->find_objects('^bar$'); 36 is(scalar @$keys, 1, 'number of keys found'); 40 Test::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 55 Test::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 ); 37 68 } 38 69 … … 73 104 like($@, qr/2 were expected/, "too many params"); 74 105 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 109 eval { 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 }; 120 like($@, qr/rename objects across distributed database boundaries/, "rename between databases"); 121 75 122 Test::Nebulous->cleanup; -
trunk/Nebulous-Server/t/16_server_swap_objects.t
r20091 r23932 8 8 use warnings FATAL => qw( all ); 9 9 10 use Test::More tests => 8;10 use Test::More tests => 13; 11 11 12 12 use lib qw( ./t ./lib ); 13 13 14 use File::Basename qw( basename ); 14 15 use Nebulous::Server; 15 16 use Test::Nebulous; … … 21 22 ); 22 23 24 use Test::DBUnit dsn => $NEB_DB, username => $NEB_USER, password => $NEB_PASS; 25 23 26 Test::Nebulous->setup; 24 27 25 28 { 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); 28 33 29 ok($neb->swap_objects( "foo1", "foo2"), "swap succeeded");34 ok($neb->swap_objects($key1, $key2), "swap succeeded"); 30 35 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 49 Test::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 ); 33 68 34 69 is($uri1, $new_uri2, "key1 -> key2"); -
trunk/Nebulous-Server/t/75_parse_neb_key.t
r19431 r23932 10 10 use Test::More; 11 11 12 plan tests => 80;12 plan tests => 99; 13 13 14 14 use lib qw( ./t ./lib ); 15 15 16 use Nebulous::Key sqw( parse_neb_key );16 use Nebulous::Key qw( parse_neb_key ); 17 17 use Test::Nebulous; 18 18 … … 224 224 } 225 225 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 226 275 # key w/ whitespace 227 276 eval { … … 267 316 }; 268 317 like( $@, qr/requires a leading slash/, "leading slash" ); 318 319 # URI w/ volume but w/o path 320 eval { 321 my $key = parse_neb_key('neb://foo'); 322 }; 323 like( $@, qr/requires a path/, "no path" );
Note:
See TracChangeset
for help on using the changeset viewer.
