1package MogileFS::ReplicationRequest; 2use strict; 3use MogileFS::Server; 4require Exporter; 5our @ISA = qw(Exporter); 6our @EXPORT_OK = qw(rr_upgrade ALL_GOOD TOO_GOOD TEMP_NO_ANSWER); 7 8my $no_answer = bless { temp_fail => 1 }; 9sub TEMP_NO_ANSWER () { $no_answer } 10my $all_good = bless { all_good => 1 }; 11sub ALL_GOOD () { $all_good } 12my $too_good = bless { all_good => 1, too_good => 1 }; 13sub TOO_GOOD () { $too_good } 14 15# upgrades the return values from old-style ReplicationPolicy classes 16# to MogileFS::ReplicationRequest objects, unless they already are, 17# in which case they're passed through unchanged. provides peaceful 18# upgrade path for old plugins. 19sub rr_upgrade { 20 my ($rv) = @_; 21 return $rv if ref $rv; 22 return TEMP_NO_ANSWER if !defined $rv; 23 return ALL_GOOD if !$rv; 24 return MogileFS::ReplicationRequest->replicate_to($rv); 25} 26 27# for ideal replications 28sub replicate_to { 29 my ($class, @devs) = @_; 30 @devs = map { ref $_ ? $_ : Mgd::device_factory()->get_by_id($_) } @devs; 31 return bless { 32 ideal_next => \@devs, 33 }, $class; 34} 35 36sub new { 37 my ($class, %opts) = @_; 38 my $self = bless {}, $class; 39 $self->{ideal_next} = delete $opts{ideal} || []; 40 $self->{desperate_next} = delete $opts{desperate} || []; 41 Carp::croak("unknown args") if %opts; 42 return $self; 43} 44 45############################################################################ 46 47sub is_happy { 48 my $self = shift; 49 return $self->{all_good}; 50} 51 52sub too_happy { 53 my $self = shift; 54 return $self->{too_good}; 55} 56 57sub temp_fail { 58 my $self = shift; 59 return $self->{temp_fail}; 60} 61 62# returns array of MogileFS::Device objs, in preferred order, one of 63# which (but not multiple) would satisfy the replication policy 64# for its next step. at which point the replication policy needs 65# to be asked again what the next step is. 66sub copy_to_one_of_ideally { 67 my $self = shift; 68 return @{ $self->{ideal_next} || [] }; 69} 70 71# like above, but replication policy isn't happy about these choices, 72# so a reevaluation of this replication decision should be made in the 73# future, when new disks/hosts might be available. 74sub copy_to_one_of_desperate { 75 my $self = shift; 76 return @{ $self->{desperate_next} || [] }; 77} 78 79# for test suite.. 80sub t_as_string { 81 my $self = shift; 82 return "too_good" if $self->{too_good}; 83 return "all_good" if $self->{all_good}; 84 return "temp_fail" if $self->{temp_fail}; 85 my @devs; 86 if (@devs = $self->copy_to_one_of_ideally) { 87 return "ideal(" . join(",", sort {$a<=>$b} map { $_->id } @devs) . ")"; 88 } 89 if (@devs = $self->copy_to_one_of_desperate) { 90 return "desperate(" . join(",", sort {$a<=>$b} map { $_->id } @devs) . ")"; 91 } 92 die "unknown $self type"; 93} 94 951; 96 97