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;
}
foreach my $dmid (keys %singleton) {
delete $singleton{$dmid} unless $id2name{$dmid};
}
$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 propogate 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;