5 use MogileFS
::ReplicationRequest
qw(rr_upgrade);
6 use overload
'""' => \
&as_string
;
9 my ($class, $fidid) = @_;
10 croak
("Invalid fidid") unless $fidid;
19 _devids
=> undef, # undef, or pre-loaded arrayref devid list
25 "FID[f=$self->{fidid}]";
28 # mutates/blesses given row.
30 my ($class, $row) = @_;
31 # TODO: sanity check provided row more?
32 $row->{fidid
} = delete $row->{fid
} or die "Missing 'fid' column";
34 return bless $row, $class;
37 # quick port of old API. perhaps not ideal.
38 sub new_from_dmid_and_key
{
39 my ($class, $dmid, $key) = @_;
40 my $row = Mgd
::get_store
()->read_store->file_row_from_dmid_key($dmid, $key)
42 return $class->new_from_db_row($row);
45 # given a bunch of ::FID objects, populates their devids en-masse
46 # (for the fsck worker, which doesn't want to do many database
48 sub mass_load_devids
{
49 my ($class, @fids) = @_;
50 my $sto = Mgd
::get_store
();
51 my $locs = $sto->fid_devids_multiple(map { $_->id } @fids);
53 foreach my $fid (@fids) {
54 $fid->{_devids
} = $locs->{$fid->id} || [];
57 # --------------------------------------------------------------------------
62 return $self->{_loaded
};
68 return $self->{classid
};
80 return $self->{length};
86 return $self->{devcount
};
89 sub id
{ $_[0]{fidid
} }
91 # force loading, or die.
93 return 1 if $_[0]{_loaded
};
95 croak
("FID\#$self->fidid} doesn't exist") unless $self->_tryload;
98 # return 1 if loaded, or 0 if not exist
100 return 1 if $_[0]{_loaded
};
102 my $row = Mgd
::get_store
()->file_row_from_fidid($self->{fidid
})
104 $self->{$_} = $row->{$_} foreach qw(dmid dkey length classid devcount);
105 $self->{_loaded
} = 1;
109 sub update_devcount
{
110 my ($self, %opts) = @_;
112 my $no_lock = delete $opts{no_lock
};
113 croak
"Bogus options" if %opts;
115 my $fidid = $self->{fidid
};
117 my $sto = Mgd
::get_store
();
119 return $sto->update_devcount($fidid);
121 return $sto->update_devcount_atomic($fidid);
126 my ($self, %opts) = @_;
128 my $classid = delete $opts{classid
};
129 croak
"Bogus options" if %opts;
131 my $sto = Mgd
::get_store
();
132 return $sto->update_classid($self->{fidid
}, $classid);
135 sub enqueue_for_replication
{
136 my ($self, %opts) = @_;
137 my $in = delete $opts{in};
138 my $from_dev = delete $opts{from_device
}; # devid or Device object
139 croak
("Unknown options to enqueue_for_replication") if %opts;
140 my $from_devid = (ref $from_dev ?
$from_dev->id : $from_dev) || undef;
141 Mgd
::get_store
()->enqueue_for_replication($self->id, $from_devid, $in);
144 sub mark_unreachable
{
146 # update database table
147 Mgd
::get_store
()->mark_fidid_unreachable($self->id);
152 my $sto = Mgd
::get_store
();
153 $sto->delete_fidid($fid->id);
156 # returns 1 on success, 0 on duplicate key error, dies on exception
158 my ($fid, $to_key) = @_;
159 my $sto = Mgd
::get_store
();
160 return $sto->rename_file($fid->id, $to_key);
163 # returns array of devids that this fid is on
164 # NOTE: TODO: by default, this doesn't cache. callers might be surprised from
165 # having an old version later on. before caching is added, auditing needs
170 # if it was mass-loaded and stored in _devids arrayref, use
171 # that instead of going to db...
172 return @
{$self->{_devids
}} if $self->{_devids
};
174 # else get it from the database
175 return Mgd
::get_store
()->read_store->fid_devids($self->id);
180 return map { MogileFS
::Device
->of_devid($_) } $self->devids;
185 return map { MogileFS
::DevFID
->new($_, $self) } $self->devids;
192 return MogileFS
::Class
->of_fid($self);
195 # Get reloaded the next time we're bothered.
198 $self->{_loaded
} = 0;
201 # returns bool: if fid's presumed-to-be-on devids meet the file class'
202 # replication policy rules. dies on failure to load class, world
204 sub devids_meet_policy
{
206 my $cls = $self->class;
208 my $polobj = $cls->repl_policy_obj;
210 my $alldev = MogileFS
::Device
->map
211 or die "No global device map";
213 my @devs = $self->devs;
214 # This is a little heavy handed just to fix the 'devcount' cache, but
215 # doing it here ensures we get the error logged.
216 if (@devs != $self->devcount) {
225 min
=> $cls->mindevcount,
227 my $rr = rr_upgrade
($polobj->replicate_to(%rep_args));
228 return $rr->is_happy && ! $rr->too_happy;
232 my ($self, $code, $dev) = @_;
233 Mgd
::get_store
()->fsck_log(
236 devid
=> ($dev ?
$dev->id : undef),
241 sub forget_cached_devids
{
243 $self->{_devids
} = undef;
246 # returns MogileFS::DevFID object, after noting in the db that this fid is on this DB.
247 # it trusts you that it is, and that you've verified it.
249 my ($fid, $dev) = @_;
250 my $dfid = MogileFS
::DevFID
->new($dev, $fid);
252 $fid->forget_cached_devids;
256 sub forget_about_device
{
257 my ($fid, $dev) = @_;
258 $dev->forget_about($fid);
259 $fid->forget_cached_devids;
269 MogileFS::FID - represents a unique, immutable version of a file
273 This class represents a "fid", or "file id", which is a unique
274 revision of a file. If you upload a file with the same key
275 ("filename") a dozen times, each one has a unique "fid". Fids are
276 immutable, and are what are replicated around the MogileFS farm.