Changeset 24557 for branches/eam_branches/20090522/Nebulous-Server
- Timestamp:
- Jun 25, 2009, 2:00:56 PM (17 years ago)
- Location:
- branches/eam_branches/20090522
- Files:
-
- 15 deleted
- 16 edited
- 16 copied
-
. (modified) (1 prop)
-
Nebulous-Server (modified) (1 prop)
-
Nebulous-Server/Build.PL (modified) (1 diff)
-
Nebulous-Server/Changes (modified) (2 diffs)
-
Nebulous-Server/MANIFEST (modified) (1 diff)
-
Nebulous-Server/bin/neb-voladd (modified) (5 diffs)
-
Nebulous-Server/bin/nebdiskd (modified) (24 diffs)
-
Nebulous-Server/lib/Nebulous/Key.pm (modified) (10 diffs)
-
Nebulous-Server/lib/Nebulous/Server.pm (modified) (109 diffs)
-
Nebulous-Server/lib/Nebulous/Server.pod (modified) (3 diffs)
-
Nebulous-Server/lib/Nebulous/Server/Config.pm (modified) (3 diffs)
-
Nebulous-Server/lib/Nebulous/Server/SQL.pm (modified) (16 diffs)
-
Nebulous-Server/lib/Test/Nebulous.pm (modified) (3 diffs)
-
Nebulous-Server/scripts/dirize.pl (modified) (3 diffs)
-
Nebulous-Server/t/02_config.t (modified) (2 diffs)
-
Nebulous-Server/t/02_server_setup.t (deleted)
-
Nebulous-Server/t/03_server_create_object.t (deleted)
-
Nebulous-Server/t/03_server_setup.t (copied) (copied from trunk/Nebulous-Server/t/03_server_setup.t )
-
Nebulous-Server/t/04_server_create_object.t (copied) (copied from trunk/Nebulous-Server/t/04_server_create_object.t )
-
Nebulous-Server/t/04_server_replicate_object.t (deleted)
-
Nebulous-Server/t/05_server_lock_object.t (deleted)
-
Nebulous-Server/t/05_server_replicate_object.t (copied) (copied from trunk/Nebulous-Server/t/05_server_replicate_object.t )
-
Nebulous-Server/t/06_server_lock_object.t (copied) (copied from trunk/Nebulous-Server/t/06_server_lock_object.t )
-
Nebulous-Server/t/06_server_unlock_object.t (deleted)
-
Nebulous-Server/t/07_server_find_instances.t (deleted)
-
Nebulous-Server/t/07_server_unlock_object.t (copied) (copied from trunk/Nebulous-Server/t/07_server_unlock_object.t )
-
Nebulous-Server/t/08_server_delete_instance.t (deleted)
-
Nebulous-Server/t/08_server_find_instances.t (copied) (copied from trunk/Nebulous-Server/t/08_server_find_instances.t )
-
Nebulous-Server/t/09_server_delete_instance.t (copied) (copied from trunk/Nebulous-Server/t/09_server_delete_instance.t )
-
Nebulous-Server/t/09_server_stat_object.t (deleted)
-
Nebulous-Server/t/10_server_is_valid_volume_name.t (deleted)
-
Nebulous-Server/t/10_server_stat_object.t (copied) (copied from trunk/Nebulous-Server/t/10_server_stat_object.t )
-
Nebulous-Server/t/11_server_is_valid_object_key.t (deleted)
-
Nebulous-Server/t/11_server_is_valid_volume_name.t (copied) (copied from trunk/Nebulous-Server/t/11_server_is_valid_volume_name.t )
-
Nebulous-Server/t/12_server_find_objects.t (deleted)
-
Nebulous-Server/t/12_server_is_valid_object_key.t (copied) (copied from trunk/Nebulous-Server/t/12_server_is_valid_object_key.t )
-
Nebulous-Server/t/13_server_find_objects.t (copied) (copied from trunk/Nebulous-Server/t/13_server_find_objects.t )
-
Nebulous-Server/t/13_server_rename_object.t (deleted)
-
Nebulous-Server/t/14_server_rename_object.t (copied) (copied from trunk/Nebulous-Server/t/14_server_rename_object.t )
-
Nebulous-Server/t/14_server_xattr.t (deleted)
-
Nebulous-Server/t/15_mounts.t (deleted)
-
Nebulous-Server/t/15_server_xattr.t (copied) (copied from trunk/Nebulous-Server/t/15_server_xattr.t )
-
Nebulous-Server/t/16_mounts.t (copied) (copied from trunk/Nebulous-Server/t/16_mounts.t )
-
Nebulous-Server/t/16_server_swap_objects.t (deleted)
-
Nebulous-Server/t/17_server_swap_objects.t (copied) (copied from trunk/Nebulous-Server/t/17_server_swap_objects.t )
-
Nebulous-Server/t/18_server_chmod_object.t (copied) (copied from trunk/Nebulous-Server/t/18_server_chmod_object.t )
-
Nebulous-Server/t/75_parse_neb_key.t (modified) (32 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/20090522
- Property svn:mergeinfo changed
-
branches/eam_branches/20090522/Nebulous-Server
- Property svn:mergeinfo changed
-
branches/eam_branches/20090522/Nebulous-Server/Build.PL
r23932 r24557 10 10 requires => { 11 11 'Apache2::Const' => 0, 12 'Cache::Memcached' => 0, 12 13 'Class::Accessor::Fast' => 0, 13 14 'Config::YAML' => '1.42', -
branches/eam_branches/20090522/Nebulous-Server/Changes
r23932 r24557 2 2 3 3 0.17 4 - add basic valid key caching via memcached 5 - add params checking to Nebulous::Key::parse_neb_key() 6 - restrict creation/modification/remove of xattrs to the user.* namespace 7 - add chmod_object() method 4 8 - retry database transactions when a deadlock is detected 5 9 - add log4perl logging to nebdiskd … … 16 20 - change 'log_level' param to 'trace' 17 21 - refactor ->find_objects() functionality 22 - rename Nebulous::Key->soft_volume Nebulous::Key->hard_volume and invert 23 the semantics 24 - add nebdiskd mountpoint test retyring 25 - rework delete_instance() to avoid requiring an index on instance.uri 26 - nebdiskd bug fixes: fix debug mode outpoint going to mail, remove db 27 passwd requirement (not all dbs require a password param) 28 - completely rework how mountedvol is populated, drop mount table 29 - infinitely try to get a db handle if the connection fails 30 - add --mountpoint param to neb-voladd 18 31 19 32 0.16 -
branches/eam_branches/20090522/Nebulous-Server/MANIFEST
r23932 r24557 33 33 t/01_load.t 34 34 t/02_config.t 35 t/02_server_setup.t 36 t/03_server_create_object.t 37 t/04_server_replicate_object.t 38 t/05_server_lock_object.t 39 t/06_server_unlock_object.t 40 t/07_server_find_instances.t 41 t/08_server_delete_instance.t 42 t/09_server_stat_object.t 43 t/10_server_is_valid_volume_name.t 44 t/11_server_is_valid_object_key.t 45 t/12_server_find_objects.t 46 t/13_server_rename_object.t 47 t/14_server_xattr.t 48 t/15_mounts.t 49 t/16_server_swap_objects.t 35 t/03_server_setup.t 36 t/04_server_create_object.t 37 t/05_server_replicate_object.t 38 t/06_server_lock_object.t 39 t/07_server_unlock_object.t 40 t/08_server_find_instances.t 41 t/09_server_delete_instance.t 42 t/10_server_stat_object.t 43 t/11_server_is_valid_volume_name.t 44 t/12_server_is_valid_object_key.t 45 t/13_server_find_objects.t 46 t/14_server_rename_object.t 47 t/15_server_xattr.t 48 t/16_mounts.t 49 t/17_server_swap_objects.t 50 t/18_server_chmod_object.t 50 51 t/75_parse_neb_key.t -
branches/eam_branches/20090522/Nebulous-Server/bin/neb-voladd
r23348 r24557 19 19 use Pod::Usage qw( pod2usage ); 20 20 21 my ($db, $dbhost, $dbuser, $dbpass, $ vname, $vhost, $uri);21 my ($db, $dbhost, $dbuser, $dbpass, $mountpoint, $vname, $vhost, $uri); 22 22 23 23 $db = $ENV{'NEB_DB'} unless $db; … … 29 29 'db|d=s' => \$db, 30 30 'host=s' => \$dbhost, 31 'mountpoint|m=s' => \$mountpoint, 32 'pass|p=s' => \$dbpass, 33 'uri|u=s' => \$uri, 31 34 'user|u=s' => \$dbuser, 32 ' pass|p=s' => \$dbpass,35 'vhost=s' => \$vhost, 33 36 'vname|n=s' => \$vname, 34 'vhost=s' => \$vhost,35 'uri|u=s' => \$uri,36 37 ) || pod2usage( 2 ); 37 38 38 39 pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV; 39 pod2usage( -msg => "Required options: --db --user --pass -- vname --vhost --uri", -exitval => 2 )40 unless $db && $dbuser && $dbpass && $ vname && $vhost && $uri;40 pod2usage( -msg => "Required options: --db --user --pass --mountpoint --vname --vhost --uri", -exitval => 2 ) 41 unless $db && $dbuser && $dbpass && $mountpoint && $vname && $vhost && $uri; 41 42 42 43 my $dbh = DBI->connect( … … 59 60 die "path: $path dirived from URI: $uri does not exist"; 60 61 } 62 unless (-d $mountpoint) { 63 die "path: $mountpoint does not exist"; 64 } 61 65 62 66 print " OK\n"; … … 65 69 66 70 my $query = $dbh->prepare( $sql->new_volume ); 67 $query->execute( $vname, $vhost, $path );71 $query->execute( $vname, $vhost, $path, $mountpoint); 68 72 69 73 print " OK\n"; … … 128 132 Optional. Defaults to C<localhost>. 129 133 134 =item * --mountpoint <path> 135 136 Path to the mountpoint of the filesystem on which C<--uri> resides. 130 137 131 138 =back -
branches/eam_branches/20090522/Nebulous-Server/bin/nebdiskd
r23675 r24557 1 1 #!/usr/bin/env perl 2 2 3 # Copyright (C) 2007 Joshua Hoblitt 4 # 5 # $Id: nebdiskd,v 1.14 2008-10-16 22:51:34 jhoblitt Exp $ 3 # Copyright (C) 2007-2009 Joshua Hoblitt 6 4 7 5 use strict; … … 35 33 $user, 36 34 $group, 35 $retry, 37 36 ); 38 37 39 38 GetOptions( 40 'dbhost| h=s' => \$dbhost,39 'dbhost|H=s' => \$dbhost, 41 40 'dbpass|p=s' => \$dbpass, 42 41 'dbuser|u=s' => \$dbuser, … … 46 45 'pidfile=s' => \$pidfile, 47 46 'restart|r' => \$restart, 47 'retry=i' => \$retry, 48 48 'stop|s' => \$stop, 49 'user =s'=> \$user,49 'user|U=s' => \$user, 50 50 'verbose|v' => \$verbose, 51 51 ) || pod2usage( 2 ); … … 61 61 $dbhost ||= $c->get_dbhost || $ENV{'NEB_DBHOST'} || 'localhost'; 62 62 $dbuser ||= $c->get_dbuser || $ENV{'NEB_USER'}; 63 $dbpass ||= $c->get_dbpass || $ENV{'NEB_PASS'} ;63 $dbpass ||= $c->get_dbpass || $ENV{'NEB_PASS'} || undef; 64 64 $pidfile ||= $c->get_pidfile || "/var/tmp/nebdiskd"; 65 65 $user ||= $c->get_user || $<; # user 66 66 $group ||= $c->get_group || $); # group 67 68 my $mounts = $c->get_mounts; 67 $retry ||= $c->get_retry || 1; 68 69 #my $mounts = $c->get_mounts; 69 70 my $poll_interval = $c->get_poll_interval || 5; 70 71 … … 80 81 $c->set_pidfile($pidfile); 81 82 $c->set_poll_interval($poll_interval); 83 $c->set_retry($retry); 82 84 $c->write; 83 85 84 86 pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV; 85 pod2usage( -msg => "Required options: --db -- user --pass", -exitval => 2 )86 unless $db && $dbuser && $dbpass;87 pod2usage( -msg => "Required options: --db --dbuser", -exitval => 2 ) 88 unless $db && $dbuser; 87 89 88 90 # start up logging … … 108 110 log4perl.appender.Mailer.to = ps-ipp-ops@ifa.hawaii.edu 109 111 log4perl.appender.Mailer.subject = nebdiskd alert 110 log4perl.appender.AppError.Filter= MatchWarn 112 log4perl.appender.Mailer.buffered = 0 113 log4perl.appender.Mailer.Filter= MatchWarn 111 114 log4perl.appender.Mailer.layout = Log::Log4perl::Layout::PatternLayout 112 115 log4perl.appender.Mailer.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} | %H | %p | %M - %m%n 116 117 log4perl.appender.Limiter = Log::Log4perl::Appender::Limit 118 log4perl.appender.Limiter.appender = Mailer 119 log4perl.appender.Limiter.block_period = 300 113 120 '; 114 121 Log::Log4perl::init(\$conf); … … 136 143 poll_interval => $poll_interval, 137 144 debug => $debug, 145 retry => $retry, 138 146 ); 139 147 }; … … 155 163 my $dbhost = $p{dbhost} or return; 156 164 my $dbuser = $p{dbuser} or return; 157 my $dbpass = $p{dbpass} or return;165 # my $dbpass = $p{dbpass} or return; 158 166 my $poll_interval = $p{poll_interval} || 60; 159 167 my $debug = $p{debug} || 0; 168 my $retry = $p{retry} || 1; 160 169 161 170 # setup the db on every pass incase the database died on us … … 168 177 169 178 eval { 170 my $r_query = $dbh->prepare_cached("REPLACE INTO mount VALUES(?, ?, ?)"); 171 my $d_query = $dbh->prepare_cached("DELETE FROM mount WHERE mountpoint = ?"); 172 179 my $r_query = $dbh->prepare_cached("REPLACE INTO mountedvol SELECT *, ?, ? FROM volume WHERE mountpoint = ?"); 180 my $d_query = $dbh->prepare_cached("DELETE FROM mountedvol WHERE mountpoint = ?"); 181 182 # get list of mount points 183 my $mounts = []; 184 { 185 # there may be multiple vol_ids per mountpoint but we only need to 186 # check each mointpont once 187 my $query = $dbh->prepare_cached("SELECT DISTINCT mountpoint FROM volume"); 188 $query->execute; 189 while (my $row = $query->fetchrow_hashref) { 190 push @$mounts, $row; 191 } 192 $query->finish; 193 } 194 173 195 # determine valid mountpoints 174 196 foreach my $mnt (@$mounts) { 175 $log->debug("checking $mnt"); 197 my $mountpoint = $mnt->{'mountpoint'}; 198 $log->debug("checking $mountpoint"); 176 199 # this /SHOULD/ fail if the mount point is handled by the 177 200 # automounter and it fails to mount 178 eval { 179 unless (is_mountpoint($mnt)) { 201 my $tries = 0; 202 TEST: eval { 203 $tries++; 204 unless (is_mountpoint($mountpoint)) { 180 205 $log->warn("$mnt is not a valid mountpoint"); 181 206 } 182 207 }; 183 208 if ($@) { 209 # try is_mountpoint() again if $retry > 1 210 if ($tries < $retry) { 211 $log->warn("retrying test of $mountpoint"); 212 goto TEST; 213 } 184 214 $log->warn($@); 185 $d_query->execute($m nt);215 $d_query->execute($mountpoint); 186 216 next; 187 217 } … … 190 220 # we determine if it's a valid mountpoint incase 191 221 # is_mountpoint() invokes the automounter 192 my $dev_info = df($m nt, 1024);222 my $dev_info = df($mountpoint, 1024); 193 223 unless (defined $dev_info) { 194 $log->error("can't find device info for $m nt");224 $log->error("can't find device info for $mountpoint"); 195 225 next; 196 226 } 197 227 198 $r_query->execute($mnt, @$dev_info{qw( blocks used )}); 199 $log->debug("adding $mnt to db"); 228 # find vol_id(s) for mountpoint 229 $r_query->execute(@$dev_info{qw( blocks used )}, $mountpoint); 230 $log->debug("adding $mountpoint to db"); 200 231 201 232 } 202 233 203 $dbh->do("call getmountedvol()");204 205 $dbh->commit;206 $log->debug("commited to database");234 # $dbh->do("call getmountedvol()"); 235 236 # $dbh->commit; 237 # $log->debug("commited to database"); 207 238 }; 208 239 if ($@) { 209 $dbh->rollback;210 $log->debug("rolledback transaction");240 # $dbh->rollback; 241 # $log->debug("rolledback transaction"); 211 242 $log->logdie($@); 212 243 } … … 235 266 my %p = @_; 236 267 268 # $p{dbpass} may be undef; 269 237 270 return unless defined $p{db} 238 271 and defined $p{dbhost} 239 and defined $p{dbuser} 240 and defined $p{dbpass}; 272 and defined $p{dbuser}; 241 273 242 274 my $sql = Nebulous::Server::SQL->new; … … 249 281 RaiseError => 1, 250 282 PrintError => 1, 251 AutoCommit => 0,283 AutoCommit => 1, # don't want this to be trasnactional 252 284 }, 253 285 ); … … 255 287 eval { 256 288 $dbh->do( $sql->set_transaction_model ); 257 $dbh->commit;289 # $dbh->commit; 258 290 }; 259 291 if ($@) { 260 $dbh->rollback;292 # $dbh->rollback; 261 293 $log->logdie($@); 262 294 } … … 344 376 =head1 SYNOPSIS 345 377 346 nebdiskd [--db <db name>] [--user <db username>] [--pass <db password>] [--debug] [--pidfile <filename>] [--stop] [--restart] [--verbose] 378 nebdiskd [--db|-D <db name>] [--dbhost|-H <db hostname> 379 [--dbuser|-u <db username>] [--dbpass|-p <db password>] [--debug|-d] 380 [--user|-U <username>] [--group|-g <groupname>] [--pidfile <filename>] 381 [--retry <n>] [--stop|-s] [--restart|-r] [--verbose|-v] 347 382 348 383 =head1 DESCRIPTION … … 355 390 =over 4 356 391 357 =item * --db|- d<db name>392 =item * --db|-D <db name> 358 393 359 394 Name of database (C<namespace>) to write too. … … 362 397 variable is set. 363 398 364 =item * -- user|-u <dbusername>399 =item * --dbuser|-u <username> 365 400 366 401 Username to authenticate with. … … 369 404 variable is set. 370 405 371 =item * -- pass|-p <dbpassword>406 =item * --dbpass|-p <password> 372 407 373 408 Password to authenticate with. 409 410 Optional if defined in the F<.nebdiskdrc> file or the appropriate environment 411 variable is set or if the database does not require a password. 412 413 =item * --dbhost|-H <hostname> 414 415 Database host to connect to. 374 416 375 417 Optional if defined in the F<.nebdiskdrc> file or the appropriate environment 376 418 variable is set. 377 419 378 =item * --debug 420 =item * --debug|-d 379 421 380 422 This flag prevents the program from "daemonizing" so output can be sent to … … 397 439 instance. 398 440 399 =item * --verbose|-r 441 =item * --retry 442 443 The number of times to test a mountpoint for "mountedness" before giving up on 444 it. 445 446 =item * --verbose|-v 400 447 401 448 Turns on informational/debugging messages to be sent to the … … 403 450 with C<--debug>. 404 451 452 =item * --user|-U 453 454 user account to run daemon as. 455 456 =item * --group|-g 457 458 group to run daemon as. 459 405 460 =back 406 461 … … 415 470 =item * C<NEB_DB> 416 471 417 Equivalent to --db|- d472 Equivalent to --db|-D 418 473 419 474 =item * C<NEB_USER> 420 475 421 Equivalent to -- user|-u476 Equivalent to --dbuser|-u 422 477 423 478 =item * C<NEB_PASS> 424 479 425 Equivalent to -- pass|-p480 Equivalent to --dbpass|-p 426 481 427 482 =back … … 439 494 dbpass: '@neb@' 440 495 dbuser: nebulous 441 mounts:442 - /mnt443 - /tmp444 - /usr445 496 pidfile: /var/tmp/nebdiskd 446 497 poll_interval: 5 498 retry: 3 447 499 448 500 The values C<db>, C<dbpass>, C<dbuser>, and C<pidfile> have the same semantics … … 451 503 =over 4 452 504 453 =item * C<mounts>454 455 A list of "paths" to C<stat(2)> before mounted volumes are polled. The propose456 of this option is to attempt to keep "automounted" volumes mounted while this457 program is running.458 459 505 This value may be omitted or left blank. 460 506 … … 465 511 This value may be omitted or left blank. The default value is C<60>s. 466 512 513 =item * C<retry> 514 515 Same as C<--retry>. 516 467 517 =back 468 518 … … 481 531 =head1 COPYRIGHT 482 532 483 Copyright (C) 2007 Joshua Hoblitt. All rights reserved.533 Copyright (C) 2007-2009 Joshua Hoblitt. All rights reserved. 484 534 485 535 This program is free software; you can redistribute it and/or modify it under -
branches/eam_branches/20090522/Nebulous-Server/lib/Nebulous/Key.pm
r23932 r24557 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( Exporter Class::Accessor::Fast ); … … 14 14 use File::Spec; 15 15 use URI::file; 16 use Carp qw( croak ); 16 17 use URI; 17 18 use overload '""' => \&_stringify_key; … … 22 23 ); 23 24 24 __PACKAGE__->mk_ro_accessors(qw( path volume soft_volume ));25 __PACKAGE__->mk_ro_accessors(qw( path volume hard_volume )); 25 26 26 27 sub parse_neb_key 27 28 { 28 29 my ($key, $volume) = @_; 29 return unless defined $key; 30 31 croak "key param is not optional" unless defined $key; 32 croak "too many params" if scalar @_ > 2; 30 33 31 34 # white space is not allowed 32 35 if ($key =~ qr/\s+/) { 33 die"keys and URIs may not contain whitespace";36 croak "keys and URIs may not contain whitespace"; 34 37 } 35 38 … … 39 42 40 43 my $volume_name; 41 my $ soft_volume;44 my $hard_volume; 42 45 # if this is a valid uri 43 46 if (defined $scheme) { 44 47 # if so, does it use the neb scheme? 45 die"URI does not use the 'neb' scheme"48 croak "URI does not use the 'neb' scheme" 46 49 unless $scheme eq 'neb'; 47 50 … … 58 61 # path component to it 59 62 unless (length $path) { 60 die"neb URI scheme requires a path component";63 croak "neb URI scheme requires a path component"; 61 64 } 62 65 … … 68 71 if (defined $volume_info->{volume} and $volume_info->{volume} ne 'any') { 69 72 $volume_name = $volume_info->{volume}; 70 $ soft_volume = $volume_info->{soft_volume};73 $hard_volume = $volume_info->{hard_volume}; 71 74 } 72 75 73 76 # require a leading slash if there is no volume name 74 77 if ((not defined $volume_name) and (not $path =~ m|^/|)) { 75 die"neb URI scheme requires a leading slash, eg. neb:/";78 croak "neb URI scheme requires a leading slash, eg. neb:/"; 76 79 } 77 80 } else { … … 81 84 if (defined $volume_info->{volume} and $volume_info->{volume} ne 'any') { 82 85 $volume_name = $volume_info->{volume}; 83 $ soft_volume = $volume_info->{soft_volume};86 $hard_volume = $volume_info->{hard_volume}; 84 87 } 85 88 } … … 96 99 return __PACKAGE__->new({ 97 100 volume => $volume_name, 98 soft_volume => $soft_volume,101 hard_volume => $hard_volume, 99 102 path => $path, 100 103 }); … … 107 110 return unless defined $volume; 108 111 109 my $ soft_volume;112 my $hard_volume; 110 113 # check to see if there is a tilde and remove it if found 111 unless(defined $volume and $volume =~ s/^~//) {112 $ soft_volume = 1;114 if (defined $volume and $volume =~ s/^~//) { 115 $hard_volume = 1; 113 116 } 114 117 115 return({ volume => $volume, soft_volume => $soft_volume });118 return({ volume => $volume, hard_volume => $hard_volume }); 116 119 } 117 120 … … 122 125 123 126 my $path = $self->path; 124 my $volume = $self->volume || "";125 my $ soft_volume = $self->soft_volume ? '~' : "";126 127 return "neb://${ soft_volume}${volume}/$path";127 my $volume = $self->volume || ''; 128 my $hard_volume = $self->hard_volume ? '~' : ''; 129 130 return "neb://${hard_volume}${volume}/$path"; 128 131 } 129 132 -
branches/eam_branches/20090522/Nebulous-Server/lib/Nebulous/Server.pm
r23932 r24557 13 13 use base qw( Class::Accessor::Fast ); 14 14 15 use Cache::Memcached; 15 16 use DBI; 16 17 use Digest::SHA1 qw( sha1_hex ); 18 use Fcntl ':mode'; 17 19 use File::Basename qw( basename dirname fileparse ); 18 20 use File::ExtAttr qw( setfattr ); … … 27 29 use URI::file; 28 30 29 __PACKAGE__->mk_accessors(qw( log sql config )); 30 31 use constant SUBPATH_DEPTH => 2; 32 use constant NFS_RETRIES => 100; 31 __PACKAGE__->mk_accessors(qw( log sql config cache )); 32 33 use constant SUBPATH_DEPTH => 2; 34 use constant NFS_RETRIES => 100; 35 use constant NFS_RETRY_WAIT => 1; 36 use constant TRANS_RETRY_WAIT => 1; 37 38 # transaction restart/retry regex 39 my $trans_regex = qr/Deadlock Found|Lock wait timeout exceeded|try restarting transaction|Can't connect to MySQL server/i; 33 40 34 41 sub new … … 45 52 sub new_from_config 46 53 { 47 my ($class, $config) = @_; 54 my $class = shift; 55 56 my ($config) = @_; 48 57 49 58 # log4perl is not avaliable until we call init() … … 51 60 my $log = Log::Log4perl::get_logger( "Nebulous::Server" ); 52 61 $log->level($config->trace); 62 $log->debug( "entered - @_" ); 53 63 54 64 my $sql = Nebulous::Server::SQL->new; 55 56 $log->debug( "entered - @_" );57 65 58 66 my $self = bless {}, ref $class || $class; … … 60 68 $self->sql($sql); 61 69 $self->config($config); 70 $self->cache( 71 Cache::Memcached->new({ 72 servers => $config->memcached_servers, 73 }) 74 ); 75 # $self->cache->set("foo", "bar") or die "set failed"; 76 # $self->cache->get("foo") or die "get failed"; 77 $log->logdie("at least one database must be defined") unless $config->n_db; 78 79 # cause a db session to be started 80 $self->_db_for_index(0); 62 81 63 82 $log->debug( "leaving" ); … … 70 89 sub _db_index_for_key 71 90 { 72 my ($self, $key) = @_; 91 my $self = shift; 92 93 my $log = $self->log; 94 $log->debug( "entered - @_" ); 95 96 my ($key) = @_; 73 97 74 98 my $config = $self->config; 75 99 76 100 my $db_index = 0; 77 die "key not defined"unless defined $key;101 $log->logdie("key not defined") unless defined $key; 78 102 79 103 # hash the key to select the correct database instance … … 85 109 $db_index = unpack("h8", sha1_hex($path)) % $config->n_db; 86 110 111 $log->debug("index is $db_index"); 112 $log->debug("leaving"); 113 87 114 return $db_index; 88 115 } … … 90 117 sub _db_for_index 91 118 { 92 my ($self, $db_index) = @_;119 my $self = shift; 93 120 94 121 my $log = $self->log; 122 $log->debug( "entered - @_" ); 123 124 my ($db_index) = @_; 125 95 126 my $sql = $self->sql; 96 127 my $config = $self->config; … … 108 139 # lookup database info 109 140 my $db_config = $config->db($db_index); 110 die "can't find database configuration info for database # $db_index"141 $log->logdie("can't find database configuration info for db # $db_index") 111 142 unless $db_config; 112 143 … … 116 147 # processes and the database might have gone away on us. Apache::DBI will 117 148 # take care of getting a valid dbh back. 118 eval { 119 $dbh = DBI->connect_cached( 120 $db_config->dsn, 121 $db_config->dbuser, 122 $db_config->dbpasswd, 123 { 124 RaiseError => 1, 125 PrintError => 0, 126 AutoCommit => 0, 127 }, 128 ); 129 130 $dbh->do( $sql->set_transaction_model ); 131 $log->debug( "connected to database: ", sub { $dbh->data_sources; } ); 132 $dbh->commit; 133 $log->debug("commit"); 134 }; 135 if ( $@ ) { 136 $dbh->rollback if $dbh; 137 $log->debug("rollback"); 138 $log->logdie( "database error: $@" ); 149 TRANS: while (1) { 150 eval { 151 $dbh = DBI->connect_cached( 152 $db_config->dsn, 153 $db_config->dbuser, 154 $db_config->dbpasswd, 155 { 156 RaiseError => 1, 157 PrintError => 0, 158 AutoCommit => 0, 159 }, 160 ); 161 162 $dbh->do( $sql->set_transaction_model ); 163 $log->debug( "connected to database: ", sub { $dbh->data_sources; } ); 164 $dbh->commit; 165 $log->debug("commit"); 166 }; 167 if ($@) { 168 $dbh->rollback if $dbh; 169 $log->debug("rollback") if $dbh; 170 if ($@ =~ qr/Can't connect to MySQL server/) { 171 $log->warn("database error, retrying transaction: $@"); 172 sleep TRANS_RETRY_WAIT; 173 redo TRANS; 174 } 175 $log->logdie( "database error: $@" ); 176 } 177 last; 139 178 } 140 179 141 180 $self->{dbs}[$db_index] = $dbh; 142 181 182 $log->debug("leaving"); 183 143 184 return $dbh; 144 185 } … … 148 189 my $self = shift; 149 190 191 my $log = $self->log; 192 $log->debug( "entered - @_" ); 193 150 194 my ($key) = validate_pos(@_, 151 195 { … … 154 198 ); 155 199 156 my $log = $self->log;157 200 my $sql = $self->sql; 158 201 my $config = $self->config; 159 202 160 die "key not defined"unless defined $key;203 $log->logdie("key not defined") unless defined $key; 161 204 my $db_index = $self->_db_index_for_key($key); 162 205 163 206 my $dbh = $self->_db_for_index($db_index); 207 164 208 return $dbh; 165 209 } … … 168 212 { 169 213 my $self = shift; 214 215 my $log = $self->log; 216 $log->debug( "entered - @_" ); 170 217 171 218 my ($key, $vol_name) = validate_pos(@_, … … 186 233 ); 187 234 235 my $sql = $self->sql; 236 188 237 # vol_name overrides the key implied volume 189 $key = parse_neb_key($key, $vol_name); 238 eval { 239 $key = parse_neb_key($key, $vol_name); 240 }; 241 $log->logdie("$@") if $@; 190 242 $vol_name = $key->volume; 191 243 192 my $log = $self->log;193 my $sql = $self->sql;194 244 my $db = $self->db($key); 195 196 $log->debug( "entered - @_" );197 245 198 246 # the key's volume can't be validiated on input for this method so we have … … 200 248 if (defined $vol_name 201 249 and not $self->_is_valid_volume_name($key, $key->volume)) { 202 if ($key->soft_volume) {250 unless ($key->hard_volume) { 203 251 $log->warn( "$vol_name is not a known volume name" ); 204 252 $vol_name = undef; 205 253 } else { 206 die "$vol_name is not a valid volume name"254 $log->logdie("$vol_name is not a valid volume name"); 207 255 } 208 256 } 209 257 210 258 my ($vol_id, $vol_host, $vol_path, $vol_xattr) 211 = $self->_get_storage_volume($key, $vol_name, $key-> soft_volume);259 = $self->_get_storage_volume($key, $vol_name, $key->hard_volume); 212 260 213 261 my $parent_id = $self->_resolve_dir_parent_id(key => $key, create => 1); … … 282 330 $db->rollback; 283 331 $log->debug("rollback"); 284 if ($@ =~ /Deadlock found/) { 285 $log->warn("database deadlock retrying transaction: $@"); 332 if ($@ =~ $trans_regex) { 333 $log->warn("database error, retrying transaction: $@"); 334 sleep TRANS_RETRY_WAIT; 286 335 redo TRANS; 287 336 } … … 291 340 } 292 341 342 # add new key to the cache 343 $self->cache->set($key->path, 1) if defined $self->cache; 344 $log->debug( "key added to cache" ); 345 293 346 $log->debug("leaving"); 294 347 … … 300 353 { 301 354 my $self = shift; 355 356 my $log = $self->log; 357 $log->debug( "entered - @_" ); 302 358 303 359 my %p = validate(@_, … … 322 378 my $key = $p{key}; 323 379 324 my $log = $self->log;325 380 my $sql = $self->sql; 326 381 my $db = $self->db($key); 327 328 $log->debug( "entered - @_" );329 382 330 383 # no path means '/', which has a dir_id & parent_id of 1 … … 394 447 $query->finish; 395 448 } 396 $log->logdie("failed to get LAST_INSERT_ID()")449 die("failed to get LAST_INSERT_ID()") 397 450 unless $parent_id; 398 451 399 $db->commit;452 # $db->commit; 400 453 } 401 454 }; … … 403 456 $db->rollback; 404 457 $log->debug("rollback"); 405 if ($@ =~ /Deadlock found/) { 406 $log->warn("database deadlock retrying transaction: $@"); 458 if ($@ =~ $trans_regex) { 459 $log->warn("database error, retrying transaction: $@"); 460 $parent_id = 1; 461 sleep TRANS_RETRY_WAIT; 407 462 redo TRANS; 408 463 } 464 if ($@ =~ qr/Duplicate entry/) { 465 $log->warn("Duplicate database entry, retrying transaction: $@"); 466 $parent_id = 1; 467 sleep TRANS_RETRY_WAIT; 468 redo TRANS; 469 } 409 470 $log->logdie("error: $@"); 410 471 } … … 421 482 { 422 483 my $self = shift; 484 485 my $log = $self->log; 486 $log->debug("entered - @_"); 423 487 424 488 my ($key, $newkey) = validate_pos(@_, … … 438 502 ); 439 503 504 my $sql = $self->sql; 505 440 506 # ignore volumes 441 $key = parse_neb_key($key); 442 $newkey = parse_neb_key($newkey); 443 444 my $log = $self->log; 445 my $sql = $self->sql; 507 eval { 508 $key = parse_neb_key($key); 509 }; 510 $log->logdie("$@") if $@; 511 eval { 512 $newkey = parse_neb_key($newkey); 513 }; 514 $log->logdie("$@") if $@; 515 446 516 my $db = $self->db($key); 447 448 $log->debug("entered - @_");449 517 450 518 # XXX this may require database migration in the future … … 464 532 unless ($rows == 1) { 465 533 $query->finish; 466 $log->logdie("affected row count is $rows instead of 1"); 467 } 534 die("affected row count is $rows instead of 1"); 535 } 536 537 $self->cache->delete($key->path) if defined $self->cache; 538 $self->cache->set($newkey->path, 1) if defined $self->cache; 468 539 469 540 $db->commit; … … 473 544 $db->rollback; 474 545 $log->debug("rollback"); 475 if ($@ =~ /Deadlock found/) { 476 $log->warn("database deadlock retrying transaction: $@"); 546 if ($@ =~ $trans_regex) { 547 $log->warn("database error, retrying transaction: $@"); 548 sleep TRANS_RETRY_WAIT; 477 549 redo TRANS; 478 550 } … … 491 563 my $self = shift; 492 564 565 my $log = $self->log; 566 $log->debug("entered - @_"); 567 493 568 my ($key1, $key2) = validate_pos(@_, 494 569 { … … 506 581 ); 507 582 583 my $sql = $self->sql; 584 508 585 # ignore volumes 509 $key1 = parse_neb_key($key1); 510 $key2 = parse_neb_key($key2); 511 512 my $log = $self->log; 513 my $sql = $self->sql; 586 eval { 587 $key1 = parse_neb_key($key1); 588 }; 589 $log->logdie("$@") if $@; 590 eval { 591 $key2 = parse_neb_key($key2); 592 }; 593 $log->logdie("$@") if $@; 514 594 515 595 my $dbidx1 = $self->_db_index_for_key($key1); 516 596 my $dbidx2 = $self->_db_index_for_key($key2); 517 die "cannot swap keys not stored on the same database" unless ($dbidx1 == $dbidx2); 597 $log->logdie("cannot swap keys not stored on the same database") 598 unless ($dbidx1 == $dbidx2); 518 599 519 600 my $dbh1 = $self->_db_for_index($dbidx1); 520 601 my $dbh2 = $self->_db_for_index($dbidx2); 521 die "different db handles for the same db?" unless ($dbh1 == $dbh2); 522 523 $log->debug("entered - @_"); 602 $log->logdie("different db handles for the same db?") 603 unless ($dbh1 == $dbh2); 524 604 525 605 # order of operations for the swap with a single db is: … … 543 623 unless ($rows == 1) { 544 624 $query->finish; 545 $log->logdie("affected row count is $rows instead of 1");625 die("affected row count is $rows instead of 1"); 546 626 } 547 627 } … … 556 636 unless ($rows == 1) { 557 637 $query->finish; 558 $log->logdie("affected row count is $rows instead of 1");638 die("affected row count is $rows instead of 1"); 559 639 } 560 640 } … … 569 649 unless ($rows == 1) { 570 650 $query->finish; 571 $log->logdie("affected row count is $rows instead of 1");651 die("affected row count is $rows instead of 1"); 572 652 } 573 653 } … … 579 659 $db->rollback; 580 660 $log->debug("rollback"); 581 if ($@ =~ /Deadlock found/) { 582 $log->warn("database deadlock retrying transaction: $@"); 661 if ($@ =~ $trans_regex) { 662 $log->warn("database error, retrying transaction: $@"); 663 sleep TRANS_RETRY_WAIT; 583 664 redo TRANS; 584 665 } … … 612 693 my $self = shift; 613 694 695 my $log = $self->log; 696 $log->debug("entered - @_"); 697 614 698 my ($key, $vol_name) = validate_pos(@_, 615 699 { … … 633 717 ); 634 718 719 my $sql = $self->sql; 720 635 721 # if a volume name is explicity specified then we should make the 636 722 # replication onto that volume (even if there is alread an instance on that … … 642 728 643 729 # vol_name overrides the key implied volume 644 $key = parse_neb_key($key, $vol_name); 730 eval { 731 $key = parse_neb_key($key, $vol_name); 732 }; 733 $log->logdie("$@") if $@; 645 734 $vol_name = $key->volume; 646 735 647 my $log = $self->log;648 my $sql = $self->sql;649 736 my $db = $self->db($key); 650 651 $log->debug("entered - @_");652 737 653 738 if (defined $vol_name 654 739 and not $self->_is_valid_volume_name($key, $key->volume)) { 655 if ($key->soft_volume) {740 unless ($key->hard_volume) { 656 741 $log->warn( "$vol_name is not a known volume name" ); 657 742 $vol_name = undef; 658 743 } else { 659 die "$vol_name is not a valid volume name"744 $log->logdie("$vol_name is not a valid volume name"); 660 745 } 661 746 } … … 681 766 unless ( $rows > 0 ) { 682 767 $query->finish; 683 $log->logdie( "storage object does not exist" );768 die( "storage object does not exist" ); 684 769 } 685 770 … … 725 810 $db->rollback; 726 811 # handle soft volumes 727 if (defined $vol_name and defined $key->soft_volume) {812 if (defined $vol_name and not defined $key->hard_volume) { 728 813 $log->debug("retrying with 'any' volume"); 729 814 return $self->replicate_object($key->path, 'any'); 730 815 } 731 816 $log->debug("rollback"); 732 if ($@ =~ /Deadlock found/) { 733 $log->warn("database deadlock retrying transaction: $@"); 817 if ($@ =~ $trans_regex) { 818 $log->warn("database error, retrying transaction: $@"); 819 sleep TRANS_RETRY_WAIT; 734 820 redo TRANS; 735 821 } … … 739 825 } 740 826 827 # check to see if the user.mode xattr exists 828 eval { 829 my $mode = $self->getxattr_object("$key", 'user.mode'); 830 if (defined $mode) { 831 $self->chmod_object("$key", $mode); 832 } 833 }; 834 if ($@) { 835 unless ($@ =~ qr/user.mode does not exist/) { 836 $log->logdie("error: $@"); 837 } 838 } 839 741 840 $log->debug("leaving"); 742 841 … … 748 847 { 749 848 my $self = shift; 849 850 my $log = $self->log; 851 $log->debug( "entered - @_" ); 750 852 751 853 my ( $key, $type ) = validate_pos( @_, … … 764 866 ); 765 867 868 my $sql = $self->sql; 869 766 870 # ignore volume 767 $key = parse_neb_key($key); 768 769 my $log = $self->log; 770 my $sql = $self->sql; 871 eval { 872 $key = parse_neb_key($key); 873 }; 874 $log->logdie("$@") if $@; 875 771 876 my $db = $self->db($key); 772 773 $log->debug( "entered - @_" );774 877 775 878 my $so_id; … … 785 888 unless ( $rows == 1 ) { 786 889 $query->finish; 787 $log->logdie( "storage object does not exist" );890 die( "storage object does not exist" ); 788 891 } 789 892 … … 800 903 # can't set a write lock if there are read locks 801 904 if ($write_lock) { 802 $log->logdie("can not write lock twice -- retry");905 die("can not write lock twice -- retry"); 803 906 } 804 907 805 908 if ($read_lock > 0) { 806 $log->logdie("can not write lock after read lock -- retry");909 die("can not write lock after read lock -- retry"); 807 910 } 808 911 … … 813 916 # if we affected more then one row something very bad has happened. 814 917 unless ($rows == 1) { 815 $log->logdie("affected row count is $rows instead of 1");918 die("affected row count is $rows instead of 1"); 816 919 } 817 920 … … 820 923 # can't set a read lock if there's a write lock 821 924 if ($write_lock) { 822 $log->logdie("can not read lock after write lock -- retry");925 die("can not read lock after write lock -- retry"); 823 926 } 824 927 … … 829 932 # if we affected more then one row something very bad has happened. 830 933 unless ($rows == 1) { 831 $log->logdie("affected row count is $rows instead of 1");934 die("affected row count is $rows instead of 1"); 832 935 } 833 936 } … … 840 943 $db->rollback; 841 944 $log->debug("rollback"); 842 if ($@ =~ /Deadlock found/) { 843 $log->warn("database deadlock retrying transaction: $@"); 945 if ($@ =~ $trans_regex) { 946 $log->warn("database error, retrying transaction: $@"); 947 sleep TRANS_RETRY_WAIT; 844 948 redo TRANS; 845 949 } … … 858 962 { 859 963 my $self = shift; 964 965 my $log = $self->log; 966 $log->debug( "entered - @_" ); 860 967 861 968 my ( $key, $type ) = validate_pos( @_, … … 874 981 ); 875 982 983 my $sql = $self->sql; 984 876 985 # ignore volume 877 $key = parse_neb_key($key); 878 879 my $log = $self->log; 880 my $sql = $self->sql; 986 eval { 987 $key = parse_neb_key($key); 988 }; 989 $log->logdie("$@") if $@; 990 881 991 my $db = $self->db($key); 882 883 $log->debug( "entered - @_" );884 992 885 993 my $so_id; … … 895 1003 unless ($rows == 1) { 896 1004 $query->finish; 897 $log->logdie("storage object does not exist");1005 die("storage object does not exist"); 898 1006 } 899 1007 … … 909 1017 # can't remove a write lock if it doesn't exist 910 1018 if ($read_lock) { 911 $log->logdie("can not have a write lock under a read lock");1019 die("can not have a write lock under a read lock"); 912 1020 } 913 1021 914 1022 unless ($write_lock) { 915 $log->logdie("can not remove non-existant write lock");1023 die("can not remove non-existant write lock"); 916 1024 } 917 1025 … … 922 1030 # if we affected more then one row something very bad has happened. 923 1031 unless ($rows == 1) { 924 $log->logdie("affected row count is $rows instead of 1");1032 die("affected row count is $rows instead of 1"); 925 1033 } 926 1034 } … … 929 1037 # can't remove a read lock if there aren't any 930 1038 if ($write_lock) { 931 $log->logdie("can not have a read lock under a write lock");1039 die("can not have a read lock under a write lock"); 932 1040 } 933 1041 934 1042 if ($read_lock == 0) { 935 $log->logdie("can not remove non-existant read lock");1043 die("can not remove non-existant read lock"); 936 1044 } 937 1045 … … 942 1050 # if we affected more then one row something very bad has happened. 943 1051 unless ($rows == 1) { 944 $log->logdie("affected row count is $rows instead of 1");1052 die("affected row count is $rows instead of 1"); 945 1053 } 946 1054 … … 953 1061 $db->rollback; 954 1062 $log->debug("rollback"); 955 if ($@ =~ /Deadlock found/) { 956 $log->warn("database deadlock retrying transaction: $@"); 1063 if ($@ =~ $trans_regex) { 1064 $log->warn("database error, retrying transaction: $@"); 1065 sleep TRANS_RETRY_WAIT; 957 1066 redo TRANS; 958 1067 } … … 971 1080 { 972 1081 my $self = shift; 1082 1083 my $log = $self->log; 1084 $log->debug("entered - @_"); 973 1085 974 1086 my ($key, $name, $value, $flags) = validate_pos(@_, … … 981 1093 { 982 1094 type => SCALAR, 1095 callbacks => { 1096 'xattr is in user. namespace' 1097 => sub { ($_[0]) =~ qr/^user\./ }, 1098 }, 983 1099 }, 984 1100 { … … 993 1109 ); 994 1110 1111 my $sql = $self->sql; 1112 995 1113 # ignore volume 996 $key = parse_neb_key($key); 997 998 my $log = $self->log; 999 my $sql = $self->sql; 1114 eval { 1115 $key = parse_neb_key($key); 1116 }; 1117 $log->logdie("$@") if $@; 1118 1000 1119 my $db = $self->db($key); 1001 1002 $log->debug("entered - @_");1003 1120 1004 1121 TRANS: while (1) { … … 1020 1137 if ($flags eq 'create') { 1021 1138 unless ($rows == 1) { 1022 $log->logdie( "affected row count is $rows instead of 1" );1139 die( "affected row count is $rows instead of 1" ); 1023 1140 } 1024 1141 } else { … … 1026 1143 # the case of a replace and 1 if the xattr didn't already exist. 1027 1144 unless ($rows == 1 or $rows == 2) { 1028 $log->logdie( "affected row count is $rows instead of 2" );1145 die( "affected row count is $rows instead of 2" ); 1029 1146 } 1030 1147 } … … 1036 1153 $db->rollback; 1037 1154 $log->debug("rollback"); 1038 if ($@ =~ /Deadlock found/) { 1039 $log->warn("database deadlock retrying transaction: $@"); 1155 if ($@ =~ $trans_regex) { 1156 $log->warn("database error, retrying transaction: $@"); 1157 sleep TRANS_RETRY_WAIT; 1040 1158 redo TRANS; 1041 1159 } … … 1054 1172 { 1055 1173 my $self = shift; 1174 1175 my $log = $self->log; 1176 $log->debug("entered - @_"); 1056 1177 1057 1178 my ($key, $name) = validate_pos(@_, … … 1064 1185 { 1065 1186 type => SCALAR, 1187 callbacks => { 1188 'xattr is in user. namespace' 1189 => sub { ($_[0]) =~ qr/^user\./ }, 1190 }, 1066 1191 }, 1067 1192 ); 1068 1193 1194 my $sql = $self->sql; 1195 1069 1196 # ignore volume 1070 $key = parse_neb_key($key); 1071 1072 my $log = $self->log; 1073 my $sql = $self->sql; 1197 eval { 1198 $key = parse_neb_key($key); 1199 }; 1200 $log->logdie("$@") if $@; 1201 1074 1202 my $db = $self->db($key); 1075 1076 $log->debug("entered - @_");1077 1203 1078 1204 my $value; … … 1085 1211 if ($rows == 0) { 1086 1212 $query->finish; 1087 $log->logdie( "xattr $key:$name does not exist" );1213 die( "xattr $key:$name does not exist" ); 1088 1214 } 1089 1215 # if we go more then one row bad something very bad has happened. 1090 1216 unless ($rows == 1) { 1091 1217 $query->finish; 1092 $log->logdie( "affected row count is $rows instead of 1" );1218 die( "affected row count is $rows instead of 1" ); 1093 1219 } 1094 1220 … … 1099 1225 $value = $row->{ 'value' }; 1100 1226 }; 1101 $log->logdie("database error: $@") if $@; 1227 if ($@) { 1228 if ($@ =~ /user\..*? does not exist/) { 1229 # do not log xattr does not exist messages 1230 die $@; 1231 } 1232 $log->logdie("database error: $@") if $@; 1233 } 1102 1234 1103 1235 $log->debug("leaving"); … … 1110 1242 { 1111 1243 my $self = shift; 1244 1245 my $log = $self->log; 1246 $log->debug("entered - @_"); 1112 1247 1113 1248 my ($key) = validate_pos(@_, … … 1120 1255 ); 1121 1256 1257 my $sql = $self->sql; 1258 1122 1259 # ignore volume 1123 $key = parse_neb_key($key); 1124 1125 my $log = $self->log; 1126 my $sql = $self->sql; 1260 eval { 1261 $key = parse_neb_key($key); 1262 }; 1263 $log->logdie("$@") if $@; 1264 1127 1265 my $db = $self->db($key); 1128 1129 $log->debug("entered - @_");1130 1266 1131 1267 my @xattrs; … … 1151 1287 my $self = shift; 1152 1288 1289 my $log = $self->log; 1290 $log->debug("entered - @_"); 1291 1153 1292 my ($key, $name) = validate_pos(@_, 1154 1293 { … … 1160 1299 { 1161 1300 type => SCALAR, 1301 callbacks => { 1302 'xattr is in user. namespace' 1303 => sub { ($_[0]) =~ qr/^user\./ }, 1304 }, 1162 1305 }, 1163 1306 ); 1164 1307 1308 my $sql = $self->sql; 1309 1165 1310 # ignore volume 1166 $key = parse_neb_key($key); 1167 1168 my $log = $self->log; 1169 my $sql = $self->sql; 1311 eval { 1312 $key = parse_neb_key($key); 1313 }; 1314 $log->logdie("$@") if $@; 1315 1170 1316 my $db = $self->db($key); 1171 1172 $log->debug("entered - @_");1173 1317 1174 1318 TRANS: while (1) { … … 1179 1323 $query->finish; 1180 1324 1325 # no rows affected means the xattr did not exist 1326 if ($rows == 0) { 1327 die( "xattr $key:$name does not exist" ); 1328 } 1329 1181 1330 # if we affected more then one row something very bad has happened. 1182 unless ($rows ==1) {1183 $log->logdie( "affected row count is $rows instead of 1" );1331 if ($rows > 1) { 1332 die( "affected row count is $rows instead of 1" ); 1184 1333 } 1185 1334 … … 1190 1339 $db->rollback; 1191 1340 $log->debug("rollback"); 1192 if ($@ =~ /Deadlock found/) { 1193 $log->warn("database deadlock retrying transaction: $@"); 1341 if ($@ =~ $trans_regex) { 1342 $log->warn("database error, retrying transaction: $@"); 1343 sleep TRANS_RETRY_WAIT; 1194 1344 redo TRANS; 1195 1345 } … … 1209 1359 my $self = shift; 1210 1360 1361 my $log = $self->log; 1362 $log->debug( "entered - @_" ); 1363 1211 1364 my ($pattern) = validate_pos( @_, 1212 1365 { … … 1216 1369 ); 1217 1370 1218 $pattern = parse_neb_key($pattern); 1219 1220 my $log = $self->log;1221 1222 $log-> debug( "entered - @_" );1371 1372 eval { 1373 $pattern = parse_neb_key($pattern) if defined $pattern; 1374 }; 1375 $log->logdie("$@") if $@; 1223 1376 1224 1377 unless (defined $pattern) { … … 1235 1388 $log->logdie("no keys found") unless ( scalar @keys ); 1236 1389 1390 if (defined $self->cache) { 1391 foreach my $path (@keys) { 1392 $self->cache->set($path, 1); 1393 $log->debug("key added to cache as: $path"); 1394 } 1395 } 1396 1237 1397 $log->debug( "leaving" ); 1238 1398 … … 1245 1405 1246 1406 my $self = shift; 1407 1408 my $log = $self->log; 1409 $log->debug( "entered - @_" ); 1410 1247 1411 my $index = shift; 1248 1412 my $key = shift; 1249 1413 1250 my $log = $self->log;1251 1414 my $sql = $self->sql; 1252 1415 my $db = $self->_db_for_index($index); 1253 1416 1254 $log->debug( "entered - @_" );1255 1417 1256 1418 # first check to see if the key is an exact match … … 1310 1472 my $self = shift; 1311 1473 1474 my $log = $self->log; 1475 $log->debug("entered - @_"); 1476 1312 1477 my ($key, $vol_name) = validate_pos(@_, 1313 1478 { … … 1330 1495 ); 1331 1496 1497 my $sql = $self->sql; 1498 1499 # unless ($key) { 1500 # $log->warn("key was undefined after validate_pos(), trying again..."); 1501 # return $self->find_instances(@_); 1502 # } 1503 1332 1504 # vol_name overrides the key implied volume 1333 $key = parse_neb_key($key, $vol_name); 1505 eval { 1506 $key = parse_neb_key($key, $vol_name); 1507 }; 1508 $log->logdie("$@") if $@; 1334 1509 $vol_name = $key->volume; 1335 1510 1336 my $log = $self->log;1337 my $sql = $self->sql;1338 1511 my $db = $self->db($key); 1339 1340 $log->debug("entered - @_");1341 1512 1342 1513 # the key's volume can't be validiated on input for this method so we have … … 1344 1515 if (defined $vol_name 1345 1516 and not $self->_is_valid_volume_name($key, $key->volume)) { 1346 if ($key->soft_volume) { 1517 if ($key->hard_volume) { 1518 $log->logdie("$vol_name is not a valid volume name"); 1519 } else { 1347 1520 $log->warn( "$vol_name is not a known volume name" ); 1348 1521 $vol_name = undef; 1349 } else {1350 die "$vol_name is not a valid volume name"1351 1522 } 1352 1523 } … … 1361 1532 unless ($rows > 0) { 1362 1533 $query->finish; 1363 $log->logdie("no instances on storage volume or volume is not avaiable for key: $key volume: $vol_name");1534 die("no instances on storage volume or volume is not avaiable for key: $key volume: $vol_name"); 1364 1535 } 1365 1536 } else { … … 1369 1540 unless ($rows > 0) { 1370 1541 $query->finish; 1371 $log->logdie("no instances available for key: $key");1542 die("no instances available for key: $key"); 1372 1543 } 1373 1544 } … … 1381 1552 $db->rollback; 1382 1553 # handle soft volumes 1383 if (defined $vol_name and defined $key->soft_volume) {1554 if (defined $vol_name and not defined $key->hard_volume) { 1384 1555 $log->debug("retrying with 'any' volume"); 1385 1556 return $self->find_instances($key->path, 'any'); … … 1403 1574 my $self = shift; 1404 1575 1576 my $log = $self->log; 1577 $log->debug( "entered - @_" ); 1578 1405 1579 my ($key, $uri) = validate_pos( @_, 1406 1580 { … … 1415 1589 ); 1416 1590 1591 my $sql = $self->sql; 1592 1417 1593 # ignore volume 1418 $key = parse_neb_key($key); 1419 1420 my $log = $self->log; 1421 my $sql = $self->sql; 1594 eval { 1595 $key = parse_neb_key($key); 1596 }; 1597 $log->logdie("$@") if $@; 1598 1422 1599 my $db = $self->db($key); 1423 1424 $log->debug( "entered - @_" );1425 1600 1426 1601 TRANS: while (1) { 1427 1602 eval { 1603 my $instances; 1428 1604 my $so_id; 1429 my $ins tances;1430 # get so_id1605 my $ins_id; 1606 # find so_id for key and get count of instances 1431 1607 { 1432 my $query = $db->prepare_cached( $sql->get_object_from_uri ); 1433 my $rows = $query->execute( $uri ); 1434 1608 my $query = $db->prepare_cached( $sql->get_instance_count_by_ext_id ); 1609 my $rows = $query->execute($key->path); 1435 1610 unless ( $rows > 0 ) { 1436 1611 $query->finish; 1437 $log->logdie( "no instance is associated with uri" ); 1438 } 1439 1440 $so_id = $query->fetchrow_hashref->{ 'so_id' }; 1612 die( "$key has no associated instances - this should not happen" ); 1613 } 1614 1615 my $record = $query->fetchrow_hashref; 1616 $so_id = $record->{ 'so_id' }; 1617 $instances = $record->{ 'count(ins_id)' }; 1441 1618 $query->finish; 1442 1443 } 1444 1619 } 1620 1621 # find ins_id for uri 1445 1622 { 1446 my $query = $db->prepare_cached( $sql->get_instance_count ); 1447 $query->execute( $so_id ); 1448 1449 $instances = $query->fetchrow_hashref->{ 'count(ins_id)' }; 1623 my $query = $db->prepare_cached( $sql->get_instance_by_uri ); 1624 my $rows = $query->execute($so_id, $uri); 1625 unless ( $rows > 0) { 1626 $query->finish; 1627 die( "no instance is associated with uri" ); 1628 } 1629 1630 $ins_id = $query->fetchrow_hashref->{ 'ins_id' }; 1450 1631 $query->finish; 1451 1632 } … … 1453 1634 # remove instance 1454 1635 { 1455 my $query = $db->prepare_cached( $sql->delete_instance );1456 my $rows = $query->execute( $ uri);1636 my $query = $db->prepare_cached( $sql->delete_instance_by_ins_id ); 1637 my $rows = $query->execute( $ins_id ); 1457 1638 $query->finish; 1458 1639 1459 # if we affected something other then two rows something very bad1460 # has happened1640 # if we affected something other then one row something very 1641 # bad has happened 1461 1642 unless ( $rows == 1 ) { 1462 $log->logdie( "affected row count is $rows instead of 1" );1643 die( "affected row count is $rows instead of 1" ); 1463 1644 } 1464 1645 } … … 1467 1648 # remove it too 1468 1649 if ( $instances == 1 ) { 1650 # remove key from cache 1651 $self->cache->delete($key->path) if defined $self->cache; 1652 1469 1653 # we just removed the last instance 1470 1654 my $query = $db->prepare_cached( $sql->delete_object ); … … 1474 1658 # TODO: this will have to be changed in order to support hardlinks 1475 1659 unless ( $rows == 1 ) { 1476 $log->logdie( "affected row count is $rows instead of 2" );1660 die( "affected row count is $rows instead of 2" ); 1477 1661 } 1478 1662 } … … 1484 1668 $db->rollback; 1485 1669 $log->debug("rollback"); 1486 if ($@ =~ /Deadlock found/) { 1487 $log->warn("database deadlock retrying transaction: $@"); 1670 if ($@ =~ $trans_regex) { 1671 $log->warn("database error, retrying transaction: $@"); 1672 sleep TRANS_RETRY_WAIT; 1488 1673 redo TRANS; 1489 1674 } … … 1502 1687 { 1503 1688 my $self = shift; 1689 1690 my $log = $self->log; 1691 $log->debug("entered - @_"); 1504 1692 1505 1693 my ( $key ) = validate_pos( @_, … … 1512 1700 ); 1513 1701 1702 my $sql = $self->sql; 1703 1514 1704 # ignore volume 1515 $key = parse_neb_key($key); 1516 1517 my $log = $self->log; 1518 my $sql = $self->sql; 1705 eval { 1706 $key = parse_neb_key($key); 1707 }; 1708 $log->logdie("$@") if $@; 1709 1519 1710 my $db = $self->db($key); 1520 1521 $log->debug("entered - @_");1522 1711 1523 1712 my $stat; … … 1527 1716 1528 1717 unless ($rows == 1) { 1529 $log->logdie("no storage object found");1718 die("no storage object found"); 1530 1719 } 1531 1720 … … 1548 1737 my $self = shift; 1549 1738 1739 my $log = $self->log; 1740 $log->debug("entered - @_"); 1741 1550 1742 validate_pos(@_); 1551 1743 1552 my $log = $self->log;1553 1744 my $sql = $self->sql; 1554 1745 my $db = $self->_db_for_index(0); # XXX fix as above 1555 1746 1556 $log->debug("entered - @_");1557 1558 1747 my $stats; 1559 1748 my $query; … … 1576 1765 } 1577 1766 1767 sub chmod_object 1768 { 1769 my $self = shift; 1770 1771 my $log = $self->log; 1772 $log->debug("entered - @_"); 1773 1774 my ($key, $mode) = validate_pos( @_, 1775 { 1776 type => SCALAR, 1777 callbacks => { 1778 'is valid object key' => sub { $self->_is_valid_object_key($_[0]) }, 1779 }, 1780 }, 1781 { 1782 type => SCALAR, 1783 regex => qr/\d{3,4}/, 1784 callbacks => { 1785 'is allowable mode' => sub { 1786 $_[0] == (S_IRUSR | S_IRGRP) 1787 }, 1788 }, 1789 }, 1790 ); 1791 1792 my $sql = $self->sql; 1793 1794 # ignore volume 1795 eval { 1796 $key = parse_neb_key($key); 1797 }; 1798 $log->logdie("$@") if $@; 1799 1800 my $db = $self->db($key); 1801 1802 # find all instances of this object 1803 my $locations; 1804 eval { 1805 $locations = $self->find_instances("$key"); 1806 }; 1807 $log->logdie("error: $@") if $@; 1808 1809 # update each instances 1810 foreach my $inst (@$locations) { 1811 my $path = URI->new($inst)->path; 1812 1813 $self->_retry(sub { chmod($mode, $path) }) 1814 or $log->logdie("can not chmod() $path: $!"); 1815 1816 # XXX I'm assuming that it's OK to fsync() a filehandle that's only 1817 # open for reading? Opening as w/rw here can fail if the chmod removes 1818 # write permissions. 1819 my $fh; 1820 $self->_retry(sub { open($fh, '<', $path) }) 1821 or $log->logdie("can not open() $path: $!"); 1822 1823 # fsync(3c) 1824 $self->_retry(sub { $fh->sync() }) 1825 or $log->logdie("can not sync() $path: $!"); 1826 1827 $self->_retry(sub { close($fh) }) 1828 or $log->logdie("can not close() $path: $!"); 1829 } 1830 1831 # stick an xattr on this object with the mode 1832 # XXX this would probably be better as a field in the storage_object_attr 1833 # table but since we're not planning to use this for very many objects (as 1834 # a %) it may not be worth adding the extra field at this time. 1835 eval { 1836 $self->setxattr_object("$key", 'user.mode', $mode, 'replace'); 1837 }; 1838 $log->logdie("error: $@") if $@; 1839 1840 $log->debug("leaving"); 1841 1842 return $mode; 1843 } 1578 1844 1579 1845 sub _get_storage_volume … … 1581 1847 my $self = shift; 1582 1848 1583 my ($key, $name, $soft_volume) = @_; 1584 1585 my $log = $self->log; 1586 my $sql = $self->sql; 1587 my $db = $self->db($key); 1588 1849 my $log = $self->log; 1589 1850 no warnings qw( uninitialized ); 1590 1851 $log->debug( "entered - @_" ); 1591 1852 use warnings; 1853 1854 my ($key, $name, $hard_volume) = @_; 1855 1856 my $sql = $self->sql; 1857 my $db = $self->db($key); 1592 1858 1593 1859 my ($vol_id, $vol_host, $vol_path, $xattr); … … 1605 1871 # if a volume name was specified, and is soft, and we failed to 1606 1872 # find it, fall back to any volume 1607 if ($soft_volume) {1873 unless ($hard_volume) { 1608 1874 ($vol_id, $vol_host, $vol_path, $xattr) = $self->_get_storage_volume($key); 1609 1875 return; # this just returns out of the eval not from the subroutine 1610 1876 } 1611 $log->logdie("storage volume: $name is not available");1877 die("storage volume: $name is not available"); 1612 1878 } 1613 1879 # when matching by name we shouldn't ever match more than once 1614 1880 if ($rows > 1) { 1615 1881 $query->finish; 1616 $log->logdie("affected row count is $rows instead of 1");1882 die("affected row count is $rows instead of 1"); 1617 1883 } 1618 1884 } else { … … 1623 1889 unless ($rows > 0) { 1624 1890 $query->finish; 1625 $log->logdie("no storage volume is available");1891 die("no storage volume is available for key: $key volume: $name hard_volume: $hard_volume"); 1626 1892 } 1627 1893 } … … 1631 1897 $query->finish; 1632 1898 }; 1633 $log->logdie("database error: $@") if $@; 1899 if ($@) { 1900 if ($@ =~ qr/no storage volume is available/) { 1901 # this should not happen unless all volumes are full 1902 $log->error($@); 1903 $log->debug("retrying..."); 1904 return $self->_get_storage_volume(@_); 1905 } 1906 # else 1907 $log->logdie("database error: $@"); 1908 } 1634 1909 1635 1910 $log->logdie("failed to find a suitable volume" ) … … 1646 1921 my $self = shift; 1647 1922 1648 my $key = shift; 1649 1650 my $log = $self->log; 1651 my $sql = $self->sql; 1652 my $db = $self->db($key); 1653 1923 my $log = $self->log; 1654 1924 no warnings qw( uninitialized ); 1655 1925 $log->debug( "entered - @_" ); 1656 1926 use warnings; 1927 1928 my $key = shift; 1929 1930 my $sql = $self->sql; 1931 my $db = $self->db($key); 1657 1932 1658 1933 my ($vol_id, $vol_host, $vol_path, $xattr); … … 1665 1940 unless ($rows > 0) { 1666 1941 $query->finish; 1667 $log->logdie("can't find a suitable storage volume to replicate $key to");1942 die("can't find a suitable storage volume to replicate $key to"); 1668 1943 } 1669 1944 # when matching by name we shouldn't ever match more than once 1670 1945 if ($rows > 1) { 1671 1946 $query->finish; 1672 $log->logdie("affected row count is $rows instead of 1");1947 die("affected row count is $rows instead of 1"); 1673 1948 } 1674 1949 … … 1690 1965 sub _is_valid_object_key 1691 1966 { 1692 my ($self, $key) = @_; 1693 1694 $key = parse_neb_key($key); 1695 1696 my $log = $self->log; 1967 my $self = shift; 1968 1969 my $log = $self->log; 1970 $log->debug( "entered - @_" ); 1971 1972 my ($key) = @_; 1973 1697 1974 my $sql = $self->sql; 1975 1976 eval { 1977 $key = parse_neb_key($key); 1978 }; 1979 $log->logdie("$@") if $@; 1980 1981 # check cache first 1982 my $cached = $self->cache->get($key->path) if defined $self->cache; 1983 if (defined $cached) { 1984 $log->debug( "key $key found in cache as ", $key->path ); 1985 $log->debug( "leaving" ); 1986 return 1; 1987 } else { 1988 $log->debug( "key $key not found in cache" ); 1989 } 1990 1698 1991 my $db = $self->db($key); 1699 1992 … … 1712 2005 1713 2006 if (defined $ext_id) { 2007 $log->debug( "key found in db" ); 2008 # add key to cache 2009 $self->cache->set($key->path, 1) if defined $self->cache; 2010 $log->debug( "key added to cache as ", $key->path ); 2011 $log->debug( "leaving" ); 1714 2012 return 1; 1715 2013 } 1716 2014 2015 $log->debug( "key not found in db" ); 2016 $log->debug( "leaving" ); 2017 1717 2018 return; 1718 2019 } … … 1721 2022 sub _is_valid_volume_name 1722 2023 { 1723 my ($self, $key, $vol_name) = @_; 1724 1725 $key = parse_neb_key($key); 2024 my $self = shift; 2025 2026 my $log = $self->log; 2027 $log->debug( "entered - @_" ); 2028 2029 my ($key, $vol_name) = @_; 2030 2031 my $sql = $self->sql; 2032 2033 # the volume name implied by the key is ignored. $key is only needed to 2034 # select a database connection 2035 eval { 2036 $key = parse_neb_key($key); 2037 }; 2038 $log->logdie("$@") if $@; 1726 2039 my $volume_info = parse_neb_volume($vol_name); 1727 2040 1728 my $log = $self->log;1729 my $sql = $self->sql;1730 2041 my $db = $self->db($key); 1731 2042 … … 1734 2045 # handle "any" volume 1735 2046 if ($vol_name eq 'any') { 2047 $log->debug( "found volume name $vol_name" ); 2048 $log->debug( "leaving" ); 1736 2049 return 1; 1737 2050 } … … 1748 2061 1749 2062 if (defined $vol_id and defined $vol_path) { 2063 $log->debug( "found volume name $vol_name" ); 2064 $log->debug( "leaving" ); 1750 2065 return 1; 1751 2066 } 1752 2067 2068 $log->debug( "volume name $vol_name not found" ); 2069 $log->debug( "leaving" ); 2070 1753 2071 return; 1754 2072 } … … 1759 2077 my $self = shift; 1760 2078 2079 my $log = $self->log; 2080 $log->debug( "entered - @_" ); 2081 1761 2082 my ($key, $so_id, $ins_id, $vol_path, $xattr) = @_; 1762 2083 1763 my $log = $self->log;1764 2084 my $sql = $self->sql; 1765 2085 my $db = $self->db($key); … … 1770 2090 my $storage_filename = $self->_generate_storage_filename($key->path, $ins_id); 1771 2091 unless (-d $storage_path) { 1772 _retry(sub { mkpath(@_) }, $storage_path, 0, 0775)1773 or die "can't create storage path: $storage_path";2092 $self->_retry(sub { mkpath([$storage_path], 0, 0775) }) 2093 or die("can't create storage path: $storage_path"); 1774 2094 } 1775 2095 # check to make sure at least the parent directory has the proper 1776 2096 # permissions 1777 my $mode = [ _retry(sub { stat($storage_path) } )]->[2] & 07777;2097 my $mode = [$self->_retry(sub { stat($storage_path) } )]->[2] & 07777; 1778 2098 unless ($mode == 0775) { 1779 $log->error("$storage_path has the wrong permissions of: %04x", $mode); 1780 _retry(sub { chmod(0775, $storage_path) }) or die "can't chmod $storage_path: $!"; 2099 # XXX: this problem is so common that it's flooding the logs 2100 $log->debug("$storage_path has the wrong permissions of: 0", sprintf("%o", $mode)); 2101 $self->_retry(sub { chmod(0775, $storage_path) }) 2102 or die("can not chmod() $storage_path: $!"); 1781 2103 } 1782 2104 … … 1787 2109 }; 1788 2110 if ($@) { 2111 if (defined $uri and -e $uri->file) { 2112 unlink($uri->file) 2113 or $log->error("failed to unlink() $uri: $!"); 2114 } 1789 2115 $log->logdie($@); 1790 2116 } … … 1792 2118 if ($xattr) { 1793 2119 my $path = $uri->file; 1794 die "can not set xattr on $path: $!"2120 $log->logdie("can not set xattr on $path: $!") 1795 2121 unless (setfattr($path, 'user.nebulous_key', $key->path)); 1796 2122 } … … 1804 2130 my $self = shift; 1805 2131 2132 my $log = $self->log; 2133 $log->debug( "entered - @_" ); 2134 1806 2135 my ($path) = @_; 1807 2136 1808 2137 # perl's open() can't do an O_CREAT | O_EXCL 1809 die "file $path already exists" if (-e $path); 2138 # XXX is it possible to tell if this system call failed? 2139 -e $path 2140 and $log->logdie("file $path already exists"); 1810 2141 1811 2142 my $fh; 1812 die "can not open $path: $!"1813 unless (_retry(sub { open($fh, '>', $path) }));2143 $self->_retry(sub { open($fh, '>', $path) }) 2144 or $log->logdie("can not open() $path: $!"); 1814 2145 1815 2146 # chmod before fsync() to make sure the changed perms hit the disk too 1816 die "can not chmod $path: $!" 1817 unless (_retry(sub { chmod(0664, $path) })); 1818 1819 die "can not flush $path: $!" 1820 unless ($fh->flush); 1821 1822 die "can not sync $path: $!" 1823 unless ($fh->sync); 1824 1825 die "can not close $path: $!" 1826 unless (_retry(sub { close($fh) })); 2147 $self->_retry(sub { chmod(0664, $path) }) 2148 or $log->logdie("can not chmod() $path: $!"); 2149 2150 $self->_retry(sub { $fh->sync() }) 2151 or $log->logdie("can not sync() $path: $!"); 2152 2153 $self->_retry(sub { close($fh) }) 2154 or $log->logdie("can not close() $path: $!"); 1827 2155 1828 2156 return $path; … … 1861 2189 sub _retry 1862 2190 { 2191 my $self = shift; 2192 2193 my $log = $self->log; 2194 $log->debug( "entered - @_" ); 2195 1863 2196 my $func = shift; 1864 2197 … … 1869 2202 }; 1870 2203 if ($@) { 1871 die $@;1872 sleep 1;2204 $log->logdie($@); 2205 sleep NFS_RETRY_WAIT; 1873 2206 next; 1874 2207 } … … 1879 2212 # if the loop ended and $@ is set, rethrow the error 1880 2213 if ($@) { 1881 die $@;2214 $log->logdie($@); 1882 2215 } 1883 2216 -
branches/eam_branches/20090522/Nebulous-Server/lib/Nebulous/Server.pod
r23932 r24557 29 29 Nebulous::Server->stat_object( $key ); 30 30 Nebulous::Server->mounts(); 31 Nebulous::Server->chmod_object( $key, $mode) ; 31 32 32 33 =head1 DESCRIPTION … … 203 204 ] 204 205 206 =item * chmod_object( $key, $mode ); 207 208 Accepts 2 parameters, both mandatory. C<$key> is the nebulous key to operate 209 on and C<$mode> are the POSIX like file permissions to set on all instances of 210 C<$key>. C<$mode> must be specified in oct. Returns C<$mode> or sucess or an 211 exception on failure. 212 205 213 =back 206 214 … … 223 231 =head1 COPYRIGHT 224 232 225 Copyright (C) 2004-200 8Joshua Hoblitt. All rights reserved.233 Copyright (C) 2004-2009 Joshua Hoblitt. All rights reserved. 226 234 227 235 This program is free software; you can redistribute it and/or modify it under -
branches/eam_branches/20090522/Nebulous-Server/lib/Nebulous/Server/Config.pm
r23932 r24557 13 13 14 14 use Log::Log4perl qw( :levels ); 15 use Params::Validate qw( validate validate_pos SCALAR );15 use Params::Validate qw( validate validate_pos SCALAR ARRAYREF ); 16 16 17 17 our %LEVELS = ( … … 46 46 }, 47 47 }, 48 dsn => { type => SCALAR, optional => 1 }, 49 dbuser => { type => SCALAR, optional => 1 }, 50 dbpasswd => { type => SCALAR, optional => 1 }, 48 dsn => { type => SCALAR, optional => 1 }, 49 dbuser => { type => SCALAR, optional => 1 }, 50 dbpasswd => { type => SCALAR, optional => 1 }, 51 memcached_servers => { type => ARRAYREF, optional => 1 }, 51 52 }; 52 53 … … 61 62 62 63 # normalize log levels to lower-case 63 my $self = { trace => $LEVELS{lc($p{trace})} }; 64 my $self = { 65 trace => $LEVELS{lc($p{trace})}, 66 memcached_servers => $p{memcached_servers}, 67 }; 64 68 65 69 bless $self, $class || ref $class; -
branches/eam_branches/20090522/Nebulous-Server/lib/Nebulous/Server/SQL.pm
r23947 r24557 175 175 WHERE ext_id = ? 176 176 }, 177 delete_instance => qq{177 delete_instance_by_ins_id => qq{ 178 178 DELETE FROM instance 179 WHERE uri= ?179 WHERE ins_id = ? 180 180 }, 181 181 get_object_from_uri => qq{ … … 184 184 WHERE uri = ? 185 185 }, 186 get_instance_by_uri => qq{ 187 SELECT ins_id 188 FROM instance 189 WHERE 190 so_id = ? 191 AND uri = ? 192 }, 186 193 get_instance_count => qq{ 187 194 SELECT count(ins_id) 188 195 FROM instance 189 196 WHERE so_id = ? 197 }, 198 get_instance_count_by_ext_id => qq{ 199 SELECT count(ins_id), so_id 200 FROM instance 201 JOIN storage_object 202 USING(so_id) 203 WHERE 204 ext_id = ? 205 GROUP BY so_id 190 206 }, 191 207 get_object_instances => qq{ … … 233 249 get_replication_volume_for_ext_id => qq{ 234 250 SELECT 235 vol_id,251 m.vol_id, 236 252 host, 237 253 path, 238 254 xattr, 239 255 total - used as free 240 FROM ( 241 -- This query works but is slow... 242 -- SELECT 243 -- mountedvol.* 244 -- FROM mountedvol 245 -- WHERE 246 -- vol_id NOT IN( 247 -- SELECT vol_id 248 -- FROM storage_object 249 -- JOIN instance 250 -- USING(so_id) 251 -- WHERE ext_id = -- 252 -- ) 253 SELECT 254 m.* 255 FROM mountedvol AS m 256 LEFT JOIN instance AS i 257 ON m.vol_id = i.vol_id 258 AND i.so_id = ( 259 SELECT so_id 260 FROM storage_object 261 WHERE ext_id = ? 262 ) 263 WHERE 264 i.vol_id IS NULL 265 ) as Foo 256 FROM mountedvol AS m 257 LEFT JOIN instance AS i 258 ON m.vol_id = i.vol_id 259 AND i.so_id = ( 260 SELECT so_id 261 FROM storage_object 262 WHERE ext_id = ? 263 ) 266 264 WHERE 267 used / total < ? 265 i.vol_id IS NULL 266 AND used / total < ? 268 267 AND available = ? 269 268 AND allocate = ? 270 ORDER BY RAND()271 LIMIT 1269 ORDER BY RAND() 270 LIMIT 1 272 271 }, 273 272 get_storage_volume => qq{ … … 287 286 }, 288 287 new_volume => qq{ 289 INSERT INTO volume (name, host, path, allocate, available, xattr )290 VALUES (?, ?, ?, TRUE, TRUE, FALSE )288 INSERT INTO volume (name, host, path, allocate, available, xattr, mountpoint) 289 VALUES (?, ?, ?, TRUE, TRUE, FALSE, ?) 291 290 }, 292 291 get_volume_by_name => qq{ … … 397 396 }, 398 397 get_mounted_volumes => qq{ 399 SELECT *FROM mountedvol ORDER BY host, name398 SELECT mountpoint, total, used, vol_id, name, host, path, allocate, available, xattr FROM mountedvol ORDER BY host, name 400 399 }, 401 400 ); … … 424 423 DROP TABLE IF EXISTS lock_record; 425 424 DROP TABLE IF EXISTS volume; 426 DROP TABLE IF EXISTS mount ;425 DROP TABLE IF EXISTS mountedvol; 427 426 DROP TABLE IF EXISTS log; 428 DROP TABLE IF EXISTS mountedvol;429 427 DROP TABLE IF EXISTS directory; 430 428 DROP PROCEDURE IF EXISTS getmountedvol; … … 455 453 FOREIGN KEY(parent_id) REFERENCES directory(dir_id), 456 454 PRIMARY KEY(dir_id), 457 KEY(parent_id) 455 KEY(parent_id), 456 KEY(dirname), 457 UNIQUE(dirname, parent_id) 458 458 ) ENGINE=innodb DEFAULT CHARSET=latin1; 459 459 … … 466 466 CREATE TABLE storage_object ( 467 467 so_id BIGINT NOT NULL AUTO_INCREMENT, 468 ext_id VARCHAR(255) NOT NULL UNIQUE,468 ext_id VARCHAR(255) NOT NULL, 469 469 ext_id_basename VARCHAR(255) NOT NULL, 470 470 dir_id BIGINT NOT NULL, … … 472 472 type enum('REG_FILE'), 473 473 PRIMARY KEY(so_id), 474 UNIQUE KEY(ext_id), 474 475 KEY(dir_id), 475 476 KEY(type) … … 514 515 CREATE TABLE volume ( 515 516 vol_id INT NOT NULL AUTO_INCREMENT, 516 name VARCHAR(255) UNIQUENOT NULL,517 name VARCHAR(255) NOT NULL, 517 518 host VARCHAR(255) NOT NULL, 518 519 path VARCHAR(255) NOT NULL, … … 520 521 available BOOLEAN DEFAULT FALSE, 521 522 xattr BOOLEAN DEFAULT FALSE, 523 mountpoint VARCHAR(255) NOT NULL, 522 524 PRIMARY KEY(vol_id), 525 UNIQUE KEY(name), 526 UNiQUE KEY(path), 523 527 KEY(host(16)), 524 KEY(path(255)),525 528 KEY(allocate), 526 KEY(available) 529 KEY(available), 530 KEY(mountpoint(255)) 531 ) ENGINE=innodb DEFAULT CHARSET=latin1; 532 533 ### 534 535 CREATE TABLE mountedvol( 536 vol_id INT NOT NULL, 537 FOREIGN KEY(vol_id) REFERENCES volume(vol_id) ON DELETE CASCADE, 538 name VARCHAR(255) NOT NULL, 539 host VARCHAR(255) NOT NULL, 540 path VARCHAR(255) NOT NULL, 541 FOREIGN KEY(path) REFERENCES volume(path) ON DELETE CASCADE, 542 allocate BOOLEAN DEFAULT FALSE, 543 available BOOLEAN DEFAULT FALSE, 544 xattr BOOLEAN DEFAULT FALSE, 545 mountpoint VARCHAR(255) NOT NULL, 546 FOREIGN KEY(mountpoint) REFERENCES volume(mountpoint) ON DELETE CASCADE, 547 total BIGINT NOT NULL, 548 used BIGINT NOT NULL, 549 PRIMARY KEY(vol_id), 550 KEY(name), 551 KEY(host), 552 KEY(path), 553 KEY(allocate), 554 KEY(available), 555 KEY(xattr), 556 KEY(mountpoint(255)) 527 557 ) ENGINE=innodb DEFAULT CHARSET=latin1; 528 558 … … 546 576 ### 547 577 548 CREATE TABLE mount (549 mountpoint VARCHAR(255) NOT NULL,550 total BIGINT NOT NULL,551 used BIGINT NOT NULL,552 PRIMARY KEY(mountpoint)553 ) ENGINE=innodb DEFAULT CHARSET=latin1;554 555 ###556 557 578 CREATE TABLE log ( 558 579 timestamp TIMESTAMP, … … 562 583 message VARCHAR(2048) NOT NULL, 563 584 PRIMARY KEY(timestamp) 564 ) ENGINE=innodb DEFAULT CHARSET=latin1;565 566 ###567 568 CREATE TABLE mountedvol(569 mountpoint VARCHAR(255) NOT NULL,570 FOREIGN KEY(mountpoint) REFERENCES mount(mountpoint) ON DELETE CASCADE,571 total BIGINT NOT NULL,572 used BIGINT NOT NULL,573 vol_id INT NOT NULL,574 FOREIGN KEY(vol_id) REFERENCES volume(vol_id) ON DELETE CASCADE,575 name VARCHAR(255) NOT NULL,576 host VARCHAR(255) NOT NULL,577 path VARCHAR(255) NOT NULL,578 FOREIGN KEY(path) REFERENCES volume(path) ON DELETE CASCADE,579 allocate BOOLEAN DEFAULT FALSE,580 available BOOLEAN DEFAULT FALSE,581 xattr BOOLEAN DEFAULT FALSE,582 PRIMARY KEY(mountpoint),583 KEY(vol_id),584 KEY(name),585 KEY(host),586 KEY(path),587 KEY(allocate),588 KEY(available),589 KEY(xattr)590 585 ) ENGINE=innodb DEFAULT CHARSET=latin1; 591 586 … … 608 603 609 604 -- store the okey checking state 610 SELECT @@FOREIGN_KEY_CHECKS INTO key_checks;605 -- SELECT @@FOREIGN_KEY_CHECKS INTO key_checks; 611 606 -- disable foregin check checks to prevent deadlocks on the mountedvol table 612 SET FOREIGN_KEY_CHECKS=0;607 -- SET FOREIGN_KEY_CHECKS=0; 613 608 614 609 -- make sure the temp table does not already exist... this can happy if the … … 629 624 OPEN cur1; 630 625 631 DELETE FROM mountedvol;632 633 626 myloop: LOOP 634 627 FETCH cur1 INTO vol_idvar, namevar, hostvar, pathvar, allocatevar, availablevar, xattrvar; 635 628 IF `done` THEN LEAVE myloop; END IF; 636 INSERTINTO mountedvol629 REPLACE INTO mountedvol 637 630 SELECT mountpoint, total, used, vol_idvar, namevar, hostvar, pathvar, allocatevar, availablevar, xattrvar 638 631 FROM … … 650 643 651 644 -- restore the original key checking state 652 SET @@FOREIGN_KEY_CHECKS = key_checks;645 -- SET @@FOREIGN_KEY_CHECKS = key_checks; 653 646 654 647 DROP TABLE IF EXISTS myvolume; 655 648 656 SET FOREIGN_KEY_CHECKS=1;649 -- SET FOREIGN_KEY_CHECKS=1; 657 650 658 651 COMMIT; -
branches/eam_branches/20090522/Nebulous-Server/lib/Test/Nebulous.pm
r19493 r24557 11 11 use base qw( Exporter ); 12 12 13 use Cache::Memcached; 13 14 use DBI; 14 15 use File::Path qw( mkpath rmtree ); … … 16 17 use Nebulous::Server::SQL; 17 18 18 our @EXPORT = qw( $NEB_DB $NEB_USER $NEB_PASS );19 our @EXPORT = qw( $NEB_DB $NEB_USER $NEB_PASS $NEB_MEMCACHED_SERVERS); 19 20 20 21 our $NEB_DB = $ENV{'NEB_DB'} || "DBI:mysql:database=test:host=localhost"; 21 22 our $NEB_USER = $ENV{'NEB_USER'} || "test"; 22 23 our $NEB_PASS = $ENV{'NEB_PASS'} || ''; 24 our $NEB_MEMCACHED_SERVERS = ['127.0.0.1:11211']; 23 25 24 26 my $dbh = DBI->connect( $NEB_DB, $NEB_USER, $NEB_PASS ); … … 53 55 54 56 # node01/node02: allocate = TRUE 55 $dbh->do(qq{ INSERT INTO volume (vol_id, name, host, path, allocate, available) VALUES (1, 'node01', 'node01', ?, TRUE, TRUE) }, undef, $dir1); 56 $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e7) }, undef, $dir1); 57 $dbh->do(qq{ INSERT INTO volume (vol_id, name, host, path, mountpoint, allocate, available) VALUES (1, 'node01', 'node01', ?, '/', TRUE, TRUE) }, undef, $dir1); 58 $dbh->do(qq{ INSERT INTO mountedvol SELECT *, 10e10, 10e7 FROM volume WHERE vol_id = ? }, undef, 1); 59 # $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e7) }, undef, $dir1); 57 60 58 $dbh->do(qq{ INSERT INTO volume (vol_id, name, host, path, allocate, available) VALUES (2, 'node02', 'node02', ?, TRUE, TRUE) }, undef, $dir2); 59 $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e8) }, undef, $dir2); 61 $dbh->do(qq{ INSERT INTO volume (vol_id, name, host, path, mountpoint, allocate, available) VALUES (2, 'node02', 'node02', ?, '/', TRUE, TRUE) }, undef, $dir2); 62 $dbh->do(qq{ INSERT INTO mountedvol SELECT *, 10e10, 10e8 FROM volume WHERE vol_id = ? }, undef, 2); 63 # $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e8) }, undef, $dir2); 60 64 61 65 # node03: allocate = TRUE 62 $dbh->do(qq{ INSERT INTO volume (vol_id, name, host, path, allocate, available) VALUES (3, 'node03', 'node03', ?, TRUE, TRUE) }, undef, $dir3); 63 $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e8) }, undef, $dir3); 66 $dbh->do(qq{ INSERT INTO volume (vol_id, name, host, path, mountpoint, allocate, available) VALUES (3, 'node03', 'node03', ?, '/', TRUE, TRUE) }, undef, $dir3); 67 $dbh->do(qq{ INSERT INTO mountedvol SELECT *, 10e10, 10e8 FROM volume WHERE vol_id = ? }, undef, 3); 68 # $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e8) }, undef, $dir3); 64 69 65 70 # node04: allocate = FALSE, available = FALSE 66 $dbh->do(qq{ INSERT INTO volume (vol_id, name, host, path, allocate, available) VALUES (4, 'node04', 'node04', ?, FALSE, FALSE) }, undef, $dir4); 67 $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e7) }, undef, $dir4); 71 $dbh->do(qq{ INSERT INTO volume (vol_id, name, host, path, mountpoint, allocate, available) VALUES (4, 'node04', 'node04', ?, '/', FALSE, FALSE) }, undef, $dir4); 72 $dbh->do(qq{ INSERT INTO mountedvol SELECT *, 10e10, 10e7 FROM volume WHERE vol_id = ? }, undef, 4); 73 # $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e7) }, undef, $dir4); 68 74 69 75 # node05: allocate = FALSE, available = TRUE 70 $dbh->do(qq{ INSERT INTO volume (vol_id, name, host, path, allocate, available) VALUES (5, 'node05', 'node05', ?, FALSE, TRUE) }, undef, $dir5); 71 $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e7) }, undef, $dir5); 76 $dbh->do(qq{ INSERT INTO volume (vol_id, name, host, path, mountpoint, allocate, available) VALUES (5, 'node05', 'node05', ?, '/', FALSE, TRUE) }, undef, $dir5); 77 $dbh->do(qq{ INSERT INTO mountedvol SELECT *, 10e10, 10e7 FROM volume WHERE vol_id = ? }, undef, 5); 78 # $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e7) }, undef, $dir5); 72 79 73 80 # node06: allocate = TRUE, available = FALSE 74 $dbh->do(qq{ INSERT INTO volume (vol_id, name, host, path, allocate, available) VALUES (6, 'node06', 'node06', ?, TRUE, FALSE) }, undef, $dir6); 75 $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e7) }, undef, $dir6); 81 $dbh->do(qq{ INSERT INTO volume (vol_id, name, host, path, mountpoint, allocate, available) VALUES (6, 'node06', 'node06', ?, '/', TRUE, FALSE) }, undef, $dir6); 82 $dbh->do(qq{ INSERT INTO mountedvol SELECT *, 10e10, 10e7 FROM volume WHERE vol_id = ? }, undef, 6); 83 # $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e7) }, undef, $dir6); 76 84 77 85 # node07: full 78 $dbh->do(qq{ INSERT INTO volume (vol_id, name, host, path, allocate, available) VALUES (7, 'node07', 'node07', ?, TRUE, TRUE) }, undef, $dir7); 79 $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e10) }, undef, $dir7); 86 $dbh->do(qq{ INSERT INTO volume (vol_id, name, host, path, mountpoint, allocate, available) VALUES (7, 'node07', 'node07', ?, '/', TRUE, TRUE) }, undef, $dir7); 87 $dbh->do(qq{ INSERT INTO mountedvol SELECT *, 10e10, 10e10 FROM volume WHERE vol_id = ? }, undef, 7); 88 # $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e10) }, undef, $dir7); 80 89 81 $dbh->do(qq{ call getmountedvol() });90 # $dbh->do(qq{ call getmountedvol() }); 82 91 } 83 92 84 93 sub cleanup { 94 # memcached needs to be emptied between test runs 95 Cache::Memcached->new(servers => $NEB_MEMCACHED_SERVERS)->flush_all; 96 # if flush_all() turns out to be useless as feared 97 # my $memd = Cache::Memcached->new(servers => $NEB_MEMCACHED_SERVERS); 98 # my $query = $dbh->prepare("SELECT ext_id FROM storage_object"); 99 # if ($query->execute) { 100 # while (my $row = $query->fetchrow_hashref) { 101 # my $ext_id = $row->{ext_id}; 102 # warn "found key $ext_id\n" if $memd->get($ext_id); 103 # warn "deleted $ext_id\n" if $memd->delete($ext_id); 104 # } 105 # } 106 # $query->finish; 107 85 108 foreach my $statement (@{ $sql->get_db_clear }) { 86 109 $dbh->do( $statement ); -
branches/eam_branches/20090522/Nebulous-Server/scripts/dirize.pl
r23952 r24557 1 1 #!/usr/bin/env perl 2 3 # query to check for duplicate directory entries 4 # select count(*) from (select so.so_id, so.ext_id, so.dir_id from storage_object as so join (select dir_id, dirname, parent_id, count(*) from directory group by dirname, parent_id having count(*) > 1) as foo on so.dir_id = foo.dir_id) as foo; 2 5 3 6 use strict; … … 23 26 my $db = $neb->_db_for_index(0); 24 27 25 my $n ;26 {27 my $query = $db->prepare("SELECT COUNT(*) as n FROM storage_object");28 $query->execute;29 $n = $query->fetchrow_hashref->{'n'};30 }28 my $n = 0; 29 #{ 30 # my $query = $db->prepare("SELECT COUNT(*) as n FROM storage_object"); 31 # $query->execute; 32 # $n = $query->fetchrow_hashref->{'n'}; 33 #} 31 34 32 my $query = $db->prepare_cached("SELECT so_id, ext_id, dir_id FROM storage_object AS so WHERE so.dir_id = 0 LIMIT 1000"); 35 # repair directory duplication 36 #my $query = $db->prepare_cached("select so.so_id, so.ext_id, so.dir_id from storage_object as so join (select dir_id, dirname, parent_id, count(*) from directory group by dirname, parent_id having count(*) > 1) as foo on so.dir_id = foo.dir_id limit 1000"); 37 38 # initial directory fill in 39 my $work_query = $db->prepare_cached("SELECT so_id, ext_id, dir_id FROM storage_object AS so WHERE so.dir_id = 0 LIMIT 1000"); 40 41 my $update_query = $db->prepare_cached("UPDATE storage_object SET ext_id_basename = ?, dir_id = ? WHERE so_id = ?"); 42 43 # turn of fkeys, otherwise we can change storage_object.dir_id to a 44 # non-existant value 45 $db->do("SET FOREIGN_KEY_CHECKS=0"); 46 #$db->do("UPDATE storage_object SET dir_id = 0"); 47 48 # completely reset the directory table 49 #$db->do("DELETE FROM directory"); 50 #$db->do("ALTER TABLE directory AUTO_INCREMENT = 1"); 51 # make sure these duplicates can't happen again 52 #$db->do("alter table directory add unique key(dirname,parent_id)"); 53 # seed the root ('/') directory 54 #$db->do("INSERT INTO directory VALUES(1, '/', 1)"); 33 55 34 56 my $i = 0; 35 while ($query->execute and $query->rows) { 36 print "foo\n"; 37 while (my $row = $query->fetchrow_hashref) { 57 while ($work_query->execute and $work_query->rows) { 58 while (my $row = $work_query->fetchrow_hashref) { 38 59 $i++; 39 60 my $key = parse_neb_key($row->{'ext_id'}); … … 41 62 42 63 #printf("dirizing %20s basename: %20s parent_id %10d\n", $key, basename($row->{'ext_id'}), $parent_id); 43 printf("$i/$ndirizing %s\n", $key->path);64 # printf("$i dirizing %s\n", $key->path); 44 65 45 my $q = $db->prepare_cached("UPDATE storage_object SET ext_id_basename = ?, dir_id = ? WHERE so_id = ?"); 46 $q->execute(basename($row->{'ext_id'}), $parent_id, $row->{'so_id'}); 47 $db->commit; 66 $update_query->execute(basename($row->{'ext_id'}), $parent_id, $row->{'so_id'}); 48 67 } 49 $query->finish; 68 $db->commit; 69 printf("### COMMIT ###\n"); 70 $work_query->finish; 71 printf("dirized $i\n"); 50 72 } 73 74 $db->do("SET FOREIGN_KEY_CHECKS=1"); 75 $db->commit; -
branches/eam_branches/20090522/Nebulous-Server/t/02_config.t
r23932 r24557 8 8 use warnings; 9 9 10 use Test::More tests => 2 1;10 use Test::More tests => 22; 11 11 12 12 use lib qw( ./t ./lib ); … … 109 109 is($config_db1->dbpasswd, "boo2", "dbpasswd"); 110 110 } 111 112 # memcached_servers 113 { 114 my $config = Nebulous::Server::Config->new( 115 memcached_servers => ['127.0.0.1:11211'], 116 ); 117 118 is_deeply($config->memcached_servers, ['127.0.0.1:11211'], "memcached_servers"); 119 } -
branches/eam_branches/20090522/Nebulous-Server/t/75_parse_neb_key.t
r23932 r24557 10 10 use Test::More; 11 11 12 plan tests => 99;12 plan tests => 106; 13 13 14 14 use lib qw( ./t ./lib ); … … 28 28 is($key->path, 'foo/bar/baz/quix', 'path'); 29 29 is($key->volume, undef, 'volume name'); 30 is($key-> soft_volume, undef, 'soft volume name');30 is($key->hard_volume, undef, 'soft volume name'); 31 31 } 32 32 … … 36 36 is($key->path, 'foo/bar/baz/quix', 'path'); 37 37 is($key->volume, undef, 'volume name'); 38 is($key-> soft_volume, undef, 'soft volume name');38 is($key->hard_volume, undef, 'soft volume name'); 39 39 } 40 40 … … 44 44 is($key->path, 'foo/bar/baz/quix', 'path'); 45 45 is($key->volume, undef, 'volume name'); 46 is($key-> soft_volume, undef, 'soft volume name');46 is($key->hard_volume, undef, 'soft volume name'); 47 47 } 48 48 … … 52 52 is($key->path, 'foo/bar/baz/quix', 'path'); 53 53 is($key->volume, undef, 'volume name'); 54 is($key-> soft_volume, undef, 'soft volume name');54 is($key->hard_volume, undef, 'soft volume name'); 55 55 } 56 56 … … 60 60 is($key->path, 'foo/bar/baz/quix', 'path'); 61 61 is($key->volume, undef, 'volume name'); 62 is($key-> soft_volume, undef, 'soft volume name');62 is($key->hard_volume, undef, 'soft volume name'); 63 63 } 64 64 … … 68 68 is($key->path, 'foo/bar/baz/quix', 'path'); 69 69 is($key->volume, undef, 'volume name'); 70 is($key-> soft_volume, undef, 'soft volume name');70 is($key->hard_volume, undef, 'soft volume name'); 71 71 } 72 72 … … 77 77 is($key->path, 'foo/bar/baz/quix', 'path'); 78 78 is($key->volume, 'boing', 'volume name'); 79 is($key-> soft_volume, 1, 'soft volume name');79 is($key->hard_volume, undef, 'soft volume name'); 80 80 } 81 81 … … 85 85 is($key->path, 'foo/bar/baz/quix', 'path'); 86 86 is($key->volume, 'boing', 'volume name'); 87 is($key-> soft_volume, undef, 'soft volume name');87 is($key->hard_volume, 1, 'soft volume name'); 88 88 } 89 89 … … 94 94 is($key->path, 'bar/baz/quix', 'path'); 95 95 is($key->volume, 'foo', 'volume name'); 96 is($key-> soft_volume, 1, 'soft volume name');96 is($key->hard_volume, undef, 'soft volume name'); 97 97 } 98 98 … … 102 102 is($key->path, 'bar/baz/quix', 'path'); 103 103 is($key->volume, 'foo', 'volume name'); 104 is($key-> soft_volume, 1, 'soft volume name');104 is($key->hard_volume, undef, 'soft volume name'); 105 105 } 106 106 … … 110 110 is($key->path, 'bar/baz/quix', 'path'); 111 111 is($key->volume, 'foo', 'volume name'); 112 is($key-> soft_volume, 1, 'soft volume name');112 is($key->hard_volume, undef, 'soft volume name'); 113 113 } 114 114 … … 118 118 is($key->path, 'bar/baz/quix', 'path'); 119 119 is($key->volume, 'foo', 'volume name'); 120 is($key-> soft_volume, 1, 'soft volume name');120 is($key->hard_volume, undef, 'soft volume name'); 121 121 } 122 122 … … 126 126 is($key->path, 'bar/baz/quix', 'path'); 127 127 is($key->volume, 'foo', 'volume name'); 128 is($key-> soft_volume, 1, 'soft volume name');128 is($key->hard_volume, undef, 'soft volume name'); 129 129 } 130 130 … … 135 135 is($key->path, 'bar/baz/quix', 'path'); 136 136 is($key->volume, 'foo', 'volume name'); 137 is($key-> soft_volume, undef, 'soft volume name');137 is($key->hard_volume, 1, 'soft volume name'); 138 138 } 139 139 … … 144 144 is($key->path, 'bar/baz/quix', 'path'); 145 145 is($key->volume, 'boing', 'volume name'); 146 is($key-> soft_volume, 1, 'soft volume name');146 is($key->hard_volume, undef, 'soft volume name'); 147 147 } 148 148 … … 152 152 is($key->path, 'bar/baz/quix', 'path'); 153 153 is($key->volume, 'boing', 'volume name'); 154 is($key-> soft_volume, undef, 'soft volume name');154 is($key->hard_volume, 1, 'soft volume name'); 155 155 } 156 156 … … 160 160 is($key->path, 'bar/baz/quix', 'path'); 161 161 is($key->volume, 'foo', 'volume name'); 162 is($key-> soft_volume, 1, 'soft volume name');162 is($key->hard_volume, undef, 'soft volume name'); 163 163 } 164 164 … … 169 169 is($key->path, 'bar/baz/quix', 'path'); 170 170 is($key->volume, undef, 'volume name'); 171 is($key-> soft_volume, undef, 'soft volume name');171 is($key->hard_volume, undef, 'soft volume name'); 172 172 } 173 173 … … 178 178 is($key->path, 'bar/baz/quix', 'path'); 179 179 is($key->volume, undef, 'volume name'); 180 is($key-> soft_volume, undef, 'soft volume name');180 is($key->hard_volume, undef, 'soft volume name'); 181 181 } 182 182 … … 186 186 is($key->path, 'bar/baz/quix', 'path'); 187 187 is($key->volume, undef, 'volume name'); 188 is($key-> soft_volume, undef, 'soft volume name');188 is($key->hard_volume, undef, 'soft volume name'); 189 189 } 190 190 … … 195 195 is($key->path, 'bar/baz/quix', 'path'); 196 196 is($key->volume, 'foo', 'volume name'); 197 is($key-> soft_volume, undef, 'soft volume name');197 is($key->hard_volume, 1, 'soft volume name'); 198 198 } 199 199 … … 205 205 is($key->path, 'foo/bar/baz/quix', 'path'); 206 206 is($key->volume, undef, 'volume name'); 207 is($key-> soft_volume, undef, 'soft volume name');207 is($key->hard_volume, undef, 'soft volume name'); 208 208 } 209 209 … … 213 213 is($key->volume, undef, 'volume name'); 214 214 is($key->path, 'foo/bar/baz/quix', 'path'); 215 is($key-> soft_volume, undef, 'soft volume name');215 is($key->hard_volume, undef, 'soft volume name'); 216 216 } 217 217 … … 221 221 is($key->path, 'foo/bar/baz/quix', 'path'); 222 222 is($key->volume, undef, 'volume name'); 223 is($key-> soft_volume, undef, 'soft volume name');223 is($key->hard_volume, undef, 'soft volume name'); 224 224 } 225 225 … … 230 230 is($key->path, '', 'path'); 231 231 is($key->volume, undef, 'volume name'); 232 is($key-> soft_volume, undef, 'soft volume name');232 is($key->hard_volume, undef, 'soft volume name'); 233 233 } 234 234 … … 238 238 is($key->path, '', 'path'); 239 239 is($key->volume, undef, 'volume name'); 240 is($key-> soft_volume, undef, 'soft volume name');240 is($key->hard_volume, undef, 'soft volume name'); 241 241 } 242 242 … … 246 246 is($key->path, '', 'path'); 247 247 is($key->volume, undef, 'volume name'); 248 is($key-> soft_volume, undef, 'soft volume name');248 is($key->hard_volume, undef, 'soft volume name'); 249 249 } 250 250 … … 254 254 is($key->path, '', 'path'); 255 255 is($key->volume, undef, 'volume name'); 256 is($key-> soft_volume, undef, 'soft volume name');256 is($key->hard_volume, undef, 'soft volume name'); 257 257 } 258 258 … … 262 262 is($key->path, '', 'path'); 263 263 is($key->volume, undef, 'volume name'); 264 is($key-> soft_volume, undef, 'soft volume name');264 is($key->hard_volume, undef, 'soft volume name'); 265 265 } 266 266 … … 270 270 is($key->path, '', 'path'); 271 271 is($key->volume, undef, 'volume name'); 272 is($key->soft_volume, undef, 'soft volume name'); 272 is($key->hard_volume, undef, 'soft volume name'); 273 } 274 275 # stringification 276 277 { 278 my $txt = 'neb:///bar/baz'; 279 my $key = parse_neb_key($txt); 280 281 is("$key", $txt, "stringified"); 282 } 283 284 { 285 my $txt = 'neb://foo.0/bar/baz'; 286 my $key = parse_neb_key($txt); 287 288 is("$key", $txt, "stringified"); 289 } 290 291 { 292 my $txt = 'neb://~foo.0/bar/baz'; 293 my $key = parse_neb_key($txt); 294 295 is("$key", $txt, "stringified"); 273 296 } 274 297 … … 322 345 }; 323 346 like( $@, qr/requires a path/, "no path" ); 347 348 # params 349 eval { 350 my $key = parse_neb_key(); 351 }; 352 like( $@, qr/key param is not optional/, "no params" ); 353 354 eval { 355 my $key = parse_neb_key(undef); 356 }; 357 like( $@, qr/key param is not optional/, "key is undef" ); 358 359 eval { 360 my $key = parse_neb_key(undef, 'bar'); 361 }; 362 like( $@, qr/key param is not optional/, "key is undef" ); 363 364 eval { 365 my $key = parse_neb_key('foo', 'bar', 'foo'); 366 }; 367 like( $@, qr/too many params/, "too many params" );
Note:
See TracChangeset
for help on using the changeset viewer.
