File-FStore
view release on metacpan or search on metacpan
lib/File/FStore/File.pm view on Meta::CPAN
'text/plain' => 'txt',
);
my %_db_tags = (
# well known tags:
final_file_size => Data::Identifier->new(uuid => '1cd4a6c6-0d7c-48d1-81e7-4e8d41fdb45d'),
final_file_encoding => Data::Identifier->new(uuid => '448c50a8-c847-4bc7-856e-0db5fea8f23b'),
final_file_hash => Data::Identifier->new(uuid => '79385945-0963-44aa-880a-bca4a42e9002'),
also_has_role => Data::Identifier->new(uuid => 'd2750351-aed7-4ade-aa80-c32436cc6030'),
also_has_state => Data::Identifier->new(uuid => '4c426c3c-900e-4350-8443-e2149869fbc9'),
has_final_state => Data::Identifier->new(uuid => '54d30193-2000-4d8a-8c28-3fa5af4cad6b'),
specific_proto_file_state => Data::Identifier->new(uuid => '63da70a8-78a4-51b0-8b87-86872b474a5d'),
);
sub dbname {
my ($self) = @_;
return $self->{dbname} //= do {
my $sth = $self->_prepare('SELECT filename FROM file WHERE id = ?');
my $res;
$sth->execute($self->{dbid});
$res = $sth->fetchall_arrayref;
$res->[0][0] // croak 'Database error';
};
}
sub filename {
my ($self) = @_;
return $self->{filename} //= do {
$self->store->_file(qw(v2 store), $self->dbname);
};
}
sub open {
my ($self) = @_;
my $fh = $self->_open;
$self->stat;
$self->_detach_fh;
return $fh;
}
sub link_out {
my ($self, $filename) = @_;
link($self->filename, $filename) or croak $!;
}
sub symlink_out {
my ($self, $filename) = @_;
symlink($self->filename, $filename) or croak $!;
}
sub update {
my ($self, %opts) = @_;
my File::FStore $store = $self->store;
my $no_digests = delete($opts{no_digests});
my $on_pre_set = delete($opts{on_pre_set});
my $on_post_set = delete($opts{on_post_set});
my $inode;
my $properties;
my $digests;
croak 'Stray options passed' if scalar keys %opts;
$store->_init_link_style;
$store->in_transaction(rw => sub {
my $fh = $self->_open;
delete $self->{stat}; #clear stat cache.
$inode = $self->as('File::Information::Inode');
# Perform a verify via File::Information
unless ($no_digests) {
my $verify_result = $inode->verify;
unless ($verify_result->has_passed || $verify_result->has_no_data || $verify_result->has_insufficient_data) {
croak sprintf('File (%s) is in bad state: %s', $self->dbname, $verify_result->status);
}
}
# Perform a verify with our own data.
{
my $data = $self->get;
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
$atime,$mtime,$ctime,$blksize,$blocks) = $self->stat;
$properties = $data->{properties} //= {};
$digests = $data->{digests} //= {};
$properties->{size} //= $size;
croak 'Size missmatch' if $properties->{size} != $size;
$properties->{inode} //= $ino;
croak 'inode missmatch' if $properties->{inode} != $ino;
# Load some basic properties, first the final values, than the current ones.
foreach my $lifecycle (qw(final current)) {
if (defined(my $v = $inode->get('size', lifecycle => $lifecycle, default => undef))) {
$properties->{size} //= $v;
croak 'Size missmatch' if $properties->{size} != $v;
}
if (defined(my $v = $inode->get('mediatype', lifecycle => $lifecycle, default => undef, as => 'mediatype'))) {
$properties->{mediasubtype} //= $v;
croak sprintf('Media subtype missmatch on (%s): "%s" vs. "%s"', $self->dbname, $properties->{mediasubtype}, $v) if $properties->{mediasubtype} ne $v;
}
if (defined(my $v = $inode->get('inodeise', lifecycle => $lifecycle, default => undef, as => 'mediatype'))) {
$properties->{inodeise} //= $v;
# XXX: We ignore missmatches here. This can be for a number of reasons. Such as switches between different sources of the value.
# TODO: A better policy should be implemented later on.
}
( run in 0.749 second using v1.01-cache-2.11-cpan-39bf76dae61 )