Module-Generic

 view release on metacpan or  search on metacpan

lib/Module/Generic/File/Cache.pm  view on Meta::CPAN

    my $j = JSON->new->utf8->relaxed->allow_nonref->convert_blessed;
    # try-catch
    local $@;
    my $encoded = eval
    {
        $j->encode( $ref );
    };
    if( $@ )
    {
        return( $self->error( "An error occurred while trying to JSON encode data: $@" ) );
    };
    return( $encoded );
}

sub _fill
{
    my $self = shift( @_ );
    my $size = shift( @_ );
    my $file = shift( @_ ) || return( $self->error( "No file was provided." ) );
    return( $self->error( "Cache file found in our object is not a Module::Generic::File object." ) ) if( !$self->_is_a( $file => 'Module::Generic::File' ) );
    # The cache file does not exists; maybe it has been removed by a destroyed process ?
    if( !$file->exists )
    {
        $self->removed(1);
        return(0);
    }
    return( $self->error( "Size value provided ($size) is not an integer." ) ) if( $size !~ /^\d+$/ );
    return(1) if( $size <= 0 );
    return( $self->error( "File provided is not a Module::Generic::File file object." ) ) if( !$self->_is_a( $file => 'Module::Generic::File' ) );
    $file->seek(0,0);
    my $minimum = 32;
    my $range = 96;
    for( my $bytes = 0; $bytes < $size; $bytes += 4 )
    {
        my $rand = int( CORE::rand( $range ** 4 ) );
        my $string = '';
        for( 1..4 )
        {
            $string .= chr( $rand % $range + $minimum );
            $rand = int( $rand / $range );
        }
        $file->print( $string ) || return( $self->pass_error( $file->error ) );
    }
    $file->truncate( $file->tell );
    return(1);
}

sub _packing_method { return( shift->_set_get_scalar( '_packing_method', @_ ) ); }

sub _str2key
{
    my $self = shift( @_ );
    my $key  = shift( @_ );
    no strict 'subs';
    if( !defined( $key ) || $key eq '' )
    {
        return( Data::UUID->new->create_str );
    }
    # We do not actually use any path, but this is for standardisation with Module::Generic::SharedMem
    my $path;
    ( $key, $path ) = ref( $key ) eq 'ARRAY' ? @$key : ( $key, [getpwuid($>)]->[7] );
    $path = [getpwuid($path)]->[7] if( $path =~ /^\d+$/ );
    if( $key =~ /^\d+$/ )
    {
        my $id = $self->ftok( $key ) ||
            return( $self->error( "Unable to get a key using IPC::SysV::ftok: $!" ) );
        return( $id );
    }
    else
    {
        my $id = 0;
        $id += $_ for( unpack( "C*", $key ) );
        my $val = $self->ftok( $id );
        return( $val );
    }
}

sub DESTROY
{
    # <https://perldoc.perl.org/perlobj#Destructors>
    CORE::local( $., $@, $!, $^E, $? );
    CORE::return if( ${^GLOBAL_PHASE} eq 'DESTRUCT' );
    my $self = CORE::shift( @_ );
    CORE::return if( !CORE::defined( $self ) );
    CORE::return unless( CORE::exists( $self->{_cache_file} ) && CORE::defined( $self->{_cache_file} ) && CORE::length( $self->{_cache_file} ) );
    my $prefix = __PACKAGE__ . '::DESTROY';
    my $cache_file;
    $cache_file = $self->{_cache_file} if( CORE::length( $self->{_cache_file} ) );
    CORE::return if( !defined( $cache_file ) || !$self->_is_a( $cache_file => 'Module::Generic::File' ) );
    my $fname = "$cache_file";
    print( STDERR "\t${prefix}: Destroying object with cache file \"${fname}\"\n" ) if( $DEBUG >= 4 );
    $self->unlock;

    my $class         = CORE::ref( $self );
    my $repo          = Module::Generic::Global->new( 'cache' => $class, key => $class );
    my $file2obj_repo = Module::Generic::Global->new( 'file2object_repo' => $class, key => $class );
    $file2obj_repo->lock;
    my $f2o_data = $file2obj_repo->get;
    if( defined( $f2o_data ) && ref( $f2o_data // '' ) eq 'HASH' )
    {
        my $ref = $f2o_data->{ $fname };

        if( defined( $ref ) && ref( $ref // '' ) eq 'ARRAY' )
        {
            printf( STDERR "\t${prefix}: %d objects found for cache file \"${fname}\"\n", scalar( @$ref ) ) if( $DEBUG >= 4 );
            my $addr = Scalar::Util::refaddr( $self );
            for( my $i = 0; $i <= $#$ref; $i++ )
            {
                if( $ref->[$i] eq $addr )
                {
                    splice( @$ref, $i, 1 );
                    $i--;
                }
            }
            if( !scalar( @$ref ) )
            {
                CORE::delete( $f2o_data->{ $fname } );
            }
        }
        else
        {
            CORE::delete( $f2o_data->{ $fname } );



( run in 1.590 second using v1.01-cache-2.11-cpan-39bf76dae61 )