package MogileFS::Domain; use strict; use warnings; use MogileFS::Util qw(throw); # -------------------------------------------------------------------------- # Class methods: # -------------------------------------------------------------------------- my %singleton; # dmid -> MogileFS::Domain my %id2name; # dmid -> domainname(namespace) my %name2id; # domainname(namespace) -> dmid my $last_load = 0; # return singleton MogileFS::Domain, given a dmid sub of_dmid { my ($pkg, $dmid) = @_; return undef unless $dmid; return $singleton{$dmid} if $singleton{$dmid}; my $ns = $pkg->name_of_id($dmid) or return undef; return $singleton{$dmid} = bless { dmid => $dmid, ns => $ns, }, $pkg; } # return singleton MogileFS::Domain, given a domain(namespace) sub of_namespace { my ($pkg, $ns) = @_; return undef unless $ns; my $dmid = $pkg->id_of_name($ns) or return undef; return MogileFS::Domain->of_dmid($dmid); } # name to dmid, reloading if not in cache sub id_of_name { my ($pkg, $domain) = @_; return $name2id{$domain} if $name2id{$domain}; $pkg->reload_domains; return $name2id{$domain}; } # dmid to name, reloading if not in cache sub name_of_id { my ($pkg, $dmid) = @_; return $id2name{$dmid} if $id2name{$dmid}; $pkg->reload_domains; return $id2name{$dmid}; } # force reload of cache sub reload_domains { my $now = time(); my $sto = Mgd::get_store(); %name2id = $sto->get_all_domains; %id2name = (); while (my ($k, $v) = each %name2id) { $id2name{$v} = $k; } # Blow singleton cache on reload. Otherwise a *change* in data may not be # reflected. %singleton = (); $last_load = $now; } # FIXME: should probably have an invalidate_cache variant that only # flushes locally (for things like "get_domains" or "get_hosts", where # it needs to be locally correct for the semantics of the command, but # no need to propagate a cache invalidation to our peers) sub invalidate_cache { $last_load = 0; %id2name = (); %name2id = (); if (my $worker = MogileFS::ProcManager->is_child) { $worker->invalidate_meta("domain"); } } sub check_cache { my $pkg = shift; my $now = time(); return if $last_load > $now - 5; MogileFS::Domain->reload_domains; } sub domains { my $pkg = shift; $pkg->check_cache; return map { $pkg->of_dmid($_) } keys %id2name; } # create a new domain given a name, returns MogileFS::Domain object on success. # throws errors on failure. error codes include: # "dup" -- on duplicate name sub create { my ($pkg, $name) = @_; # throws 'dup': my $dmid = Mgd::get_store()->create_domain($name) or die "create domain didn't return a dmid"; # return the domain id we created MogileFS::Domain->invalidate_cache; return MogileFS::Domain->of_dmid($dmid); } # -------------------------------------------------------------------------- # Instance methods: # -------------------------------------------------------------------------- sub id { $_[0]->{dmid} } sub name { $_[0]->{ns} } sub has_files { my $self = shift; return 1 if $Mgd::_T_DOM_HAS_FILES; return Mgd::get_store()->domain_has_files($self->id); } sub classes { my $dom = shift; # return a bunch of class objects for this domain return MogileFS::Class->classes_of_domain($dom); } # returns true if deleted. throws exceptions on errors. exception codes: # 'has_files' if it has files. sub delete { my $self = shift; throw("has_files") if $self->has_files; # TODO: delete its classes my $rv = Mgd::get_store()->delete_domain($self->id); MogileFS::Domain->invalidate_cache; return $rv; } # returns named class of domain sub class { my ($dom, $clname) = @_; foreach my $cl (MogileFS::Class->classes_of_domain($dom)) { return $cl if $cl->name eq $clname; } return; } sub create_class { my ($dom, $clname) = @_; return MogileFS::Class->create_class($dom, $clname); } 1;