HTML-Mason

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

      request.  Implemented by David Wheeler.

    [ BUG FIXES ]

    - If any code type parameters were set in the httpd.conf file, Mason
      died trying to read them.  This bug was introduced in version 1.20.
      Task id #496.  Reported by David Wheeler.
    - $m->caller, $m->callers and $m->caller_args now return undef or an
      empty list instead of crashing when the specified stack level does not
      exist. Task id #495.  Reported by Bernhard Schmalhofer.
    - The busy_lock option to $m->cache->get did not accept did not accept
      string values for durations, like "4m".  Task id #484.  Reported by
      Igor Muratov.
    - When generating the HTML error message page, we now only use basic
      HTML escaping.  This fixes two problems.  One is that if
      HTML::Entities is not installed, using the "|h" escape flag in the
      error display component causes an endless loop.  The other is that the
      "|h" flag can mangle non-Latin-1 characters.  Task ids #497 and #494.
      Reported by Harmen and Oleg Bartunov respectively.
    - If a component generated output, then called another component via
      $m->scomp, and that other component attempted to clear the buffer and

Changes  view on Meta::CPAN

    - Added back $comp->create_time, which was renamed as $comp->load_time
      in 1.09_02, as a deprecated method.
    - Added back $interp->time and $m->current_time, which were removed in
      1.09_01, as deprecated methods.

    [ ENHANCEMENTS ]

    - Implemented the long requested user-defined escapes feature.  It is
      now possible to define your own escape flags, as well as overriding
      Mason's own 'h' and 'u' flags.
    - Implemented expire_if and busy_lock options in new $m->cache->get
      API. These retain the essence of the 1.0x options although both
      work a little differently.
    - Added new module to implement caching extensions,
      HTML::Mason::Cache::BaseCache, with accompanying documentation.
    - Enhanced Params.pod with TOC and full descriptions of all
      parameters.  Standardized rest of documentation to link to Params.pod
      when referring to a parameter.
    - When a component path is not found, but that path matches a file on
      disk, we now print an extra warning, because this indicates that the
      user does not understand the distinction between component paths and

Changes  view on Meta::CPAN

      the same as errors in the top request.

1.13  August 26, 2002 (Taiwan time)

    [ ENHANCEMENTS ]

    - Replace the regex "[A-Za-z0-9]" with "\w", which should cooperate
      better with Unicode.
    - Added a section called "Avoiding Concurrent Recomputations" to the
      Developer's Manual.  This describes how to achieve the same effect as
      was provided by the "busy locks" feature in 1.0x.
    [ BUG FIXES ]

    - When running under mod_perl, a warning was issued from
      HTML::Mason::Request::ApacheHandler's exec() method.  (reported by
      Marius Feraru)
    - The request wrapper code did not work with anonymous component.
      (reported by Bob McElrath)
    - Mason 1.10-1.12 did not cooperate with Apache::Filter, or any other
      Apache subclass that overrode the print() method.  (reported by Mark
      Moseley)

Changes  view on Meta::CPAN

      components outside of a Interp environment.
    - New mc_cache actions 'expire' and 'keys' help you peer into data cache
      files and expire selected keys.
    - Corrected Parser to properly handle \ in components (submitted by
      Ken Williams)
    - ** Took Preview out of Mason.pm; ApacheHandler used only if mod_perl
      environment. If you use the previewer, you now have to explicitly "use
      HTML::Mason::Preview" in your handler.pl.
    - Improved documentation about argument/GET/POST handling (suggested
      by Ken Williams)
    - Added cache option 'busy_lock', which prevents multiple processes
      from recomputing an expire cache value at the same time.  (suggested
      by Dennis Watson)
    - Inserted work-around for Perl 5.005 $r scoping bug (submitted by
      Rafael Weinstein)
    - Fixed "new CGI" example in Components.pod (submitted by Austin Lin)
    - Fixed "return if content-type..." line in handler.pl and Mason.pod
      (submitted by Patrick Kane)
    - Added CREDITS file

0.4  January 06, 1999

lib/HTML/Mason/Cache/BaseCache.pm  view on Meta::CPAN

# Copyright (c) 1998-2005 by Jonathan Swartz. All rights reserved.
# This program is free software; you can redistribute it and/or modify it
# under the same terms as Perl itself.

package HTML::Mason::Cache::BaseCache;
$HTML::Mason::Cache::BaseCache::VERSION = '1.60';
use strict;
use warnings;

#
# Override to handle busy_lock and expire_if.
#
sub get
{
    my ($self, $key, %params) = @_;
    die "must specify key" unless defined($key);

    foreach my $param (keys(%params)) {
        unless ($param =~ /^(busy_lock|expire_if)$/) {
            die "unknown param '$param'";
        }
    }

    $self->_conditionally_auto_purge_on_get();

    if (my $sub = $params{expire_if}) {
        $self->expire_if($key, $sub);
    }

    my $object = $self->get_object($key) or
        return undef;

    if (Cache::BaseCache::Object_Has_Expired($object))
    {
        if ($params{busy_lock}) {
            # If busy_lock value provided, set a new "temporary"
            # expiration time that many seconds forward, and return
            # undef so that this process will start recomputing.
            my $busy_lock_time = Cache::BaseCache::Canonicalize_Expiration_Time($params{busy_lock});
            $object->set_expires_at(time + $busy_lock_time);
            $self->set_object($key, $object);
        } else {
            $self->remove($key);
        }
        return undef;
    }

    return $object->get_data( );
}

lib/HTML/Mason/Cache/BaseCache.pm  view on Meta::CPAN

=item get (key, [%params])

=for html <a name="item_get"></a>

Returns the value associated with I<key> or undef if it is
non-existent or expired. This is extended with the following optional
name/value parameters:

=over

=item busy_lock => duration

If the value has expired, set its expiration time to the current time plus
I<duration> (instead of removing it from the cache) before returning undef.
This is used to prevent multiple processes from recomputing the same
expensive value simultaneously. The I<duration> may be of any form acceptable
to L<set|HTML::Mason::Cache::BaseCache/item_set>.

=item expire_if => sub

If the value exists and has not expired, call I<sub> with the cache

lib/HTML/Mason/Devel.pod  view on Meta::CPAN

are accessed frequently and take a long time to recompute.

Suppose that a particular cache value is accessed five times a
second and takes three seconds to recompute.  When the cache expires,
the first process comes in, sees that it is expired, and starts to
recompute the value.  The second process comes in and does the same thing.
This sequence continues until the first process finishes and stores
the new value.  On average, the value will be recomputed and written
to the cache 15 times!

One solution is the I<busy_lock> flag:

   my $result = $m->cache->get('key', busy_lock=>'30 sec');

In this case, when the value cannot be retrieved, C<get()> sets
the expiration time of the value 30 seconds in the future before
returning C<undef>.  This tells the first process to compute the new
value while causing subsequent processes to use the old value for 30
seconds. 

Should the 30 seconds expire before the first process is done, a second
process will start computing the new value while setting the expiration
time yet another 30 seconds in the future, and so on.

lib/HTML/Mason/Request.pm  view on Meta::CPAN

    # Implement 1.0x cache API or just return cache object.
    if ($self->data_cache_api eq '1.0') {
        return $self->_cache_1_x($cache, %old_cache_options);
    } else {
        return $cache;
    }
}

#
# Implement 1.0x cache API in terms of Cache::Cache.
# Supported: action, busy_lock, expire_at, expire_if, expire_in, expire_next, key, value
# Silently not supported: keep_in_memory, tie_class
#
sub _cache_1_x
{
    my ($self, $cache, %options) = @_;

    my $action = $options{action} || 'retrieve';
    my $key = $options{key} || 'main';
    
    if ($action eq 'retrieve') {
        
        # Validate parameters.
        if (my @invalids = grep(!/^(expire_if|action|key|busy_lock|keep_in_memory|tie_class)$/, keys(%options))) {
            param_error "cache: invalid parameter '$invalids[0]' for action '$action'\n";
        }

        # Handle expire_if.
        if (my $sub = $options{expire_if}) {
            if (my $obj = $cache->get_object($key)) {
                if ($sub->($obj->get_created_at)) {
                    $cache->expire($key);
                }
            }
        }

        # Return the value or undef, handling busy_lock.
        if (my $result = $cache->get($key, ($options{busy_lock} ? (busy_lock=>$options{busy_lock}) : ()))) {
            return $result;
        } else {
            return undef;
        }

    } elsif ($action eq 'store') {

        # Validate parameters   
        if (my @invalids = grep(!/^(expire_(at|next|in)|action|key|value|keep_in_memory|tie_class)$/, keys(%options))) {
            param_error "cache: invalid parameter '$invalids[0]' for action '$action'\n";

lib/HTML/Mason/Request.pm  view on Meta::CPAN

}

sub cache_self {
    my ($self, %options) = @_;

    return if $self->{top_stack}->[STACK_IN_CALL_SELF]->{'CACHE_SELF'};

    my (%store_options, %retrieve_options);
    my ($expires_in, $key, $cache);
    if ($self->data_cache_api eq '1.0') {
        foreach (qw(key expire_if busy_lock)) {
            $retrieve_options{$_} = $options{$_} if (exists($options{$_}));
        }
        foreach (qw(key expire_at expire_next expire_in)) {
            $store_options{$_} = $options{$_} if (exists($options{$_}));
        }
    } else {
        #
        # key, expires_in/expire_in, expire_if and busy_lock go into
        # the set and get methods as appropriate. All other options
        # are passed into $self->cache.
        #
        foreach (qw(expire_if busy_lock)) {
            $retrieve_options{$_} = delete($options{$_}) if (exists($options{$_}));
        }
        $expires_in = delete $options{expires_in} || delete $options{expire_in} || 'never';
        $key = delete $options{key} || '__mason_cache_self__';
        $cache = $self->cache(%options);
    }

    my ($output, @retval, $error);

    my $cached =

lib/HTML/Mason/Request.pm  view on Meta::CPAN

C<$m-E<gt>cache_self> caches the entire output and return result of a
component.

C<cache_self> either returns undef, or a list containing the
return value of the component followed by '1'. You should return
immediately upon getting the latter result, as this indicates
that you are inside the second invocation of the component.

C<cache_self> takes any of parameters to C<$m-E<gt>cache>
(e.g. I<cache_depth>), any of the optional parameters to
C<$cache-E<gt>get> (I<expire_if>, I<busy_lock>), and two additional
options:

=over

=item *

I<expire_in> or I<expires_in>: Indicates when the cache expires - it
is passed as the third argument to C<$cache-E<gt>set>. e.g. '10 sec',
'5 min', '2 hours'.

t/10-cache.t  view on Meta::CPAN

</%init>
EOF
                      expect => <<'EOF',
gardenia, undef, undef
EOF
                    );


#------------------------------------------------------------

    $group->add_test( name => 'busy_lock',
                      description => 'test busy_lock',
                      component => <<'EOF',
<% join(', ', $value1 || 'undef', $value2 || 'undef') %>
<%init>
my $time = time;
my $cache = $m->cache;
$cache->set('main', 'gardenia', 0);
my $value1 = $cache->get('main', busy_lock=>'10 sec');
my $value2 = $cache->get('main');
</%init>
EOF
                      expect => <<'EOF',
undef, gardenia
EOF
                    );

#------------------------------------------------------------

    $group->add_test( name => 'busy_lock_expiration',
                      description => 'test busy_lock expiration',
                      component => <<'EOF',
<% join(', ', $value1 || 'undef', $value2 || 'undef') %>
<%init>
my $time = time;
my $cache = $m->cache;
$cache->set('main', 'gardenia', 0);
my $value1 = $cache->get('main', busy_lock=>'1 sec');
sleep(1);
my $value2 = $cache->get('main');
</%init>
EOF
                      expect => <<'EOF',
undef, undef
EOF
                    );

#------------------------------------------------------------

t/10a-cache-1.0x.t  view on Meta::CPAN

</%init>
EOF
                      expect => <<'EOF',
gardenia, gardenia, undef, undef
EOF
                    );


#------------------------------------------------------------

    $group->add_test( name => 'busy_lock',
                      description => 'test busy_lock',
                      interp_params => { data_cache_api => '1.0' },
                      component => <<'EOF',
<% join(', ', $value1 || 'undef', $value2 || 'undef') %>
<%init>
my $time = time;
$m->cache(value=>'gardenia', action=>'store', expire_at=>time);
sleep(1);
my $value1 = $m->cache(busy_lock=>'10 sec');
my $value2 = $m->cache;
</%init>
EOF
                      expect => <<'EOF',
undef, gardenia
EOF
                    );

#------------------------------------------------------------

    $group->add_test( name => 'busy_lock_expiration',
                      description => 'test busy_lock expiration',
                      interp_params => { data_cache_api => '1.0' },
                      component => <<'EOF',
<% join(', ', $value1 || 'undef', $value2 || 'undef') %>
<%init>
my $time = time;
$m->cache(value=>'gardenia', action=>'store', expire_at=>time);
sleep(1);
my $value1 = $m->cache(busy_lock=>'1 sec');
sleep(1);
my $value2 = $m->cache;
</%init>
EOF
                      expect => <<'EOF',
undef, undef
EOF
                    );

#------------------------------------------------------------

t/10b-cache-chi.t  view on Meta::CPAN

</%init>
EOF
                      expect => <<'EOF',
gardenia, undef
EOF
                    );


#------------------------------------------------------------

    $group->add_test( name => 'busy_lock',
                      description => 'test busy_lock',
                      %chi_interp_params,
                      component => <<'EOF',
<% join(', ', $value1 || 'undef', $value2 || 'undef') %>
<%init>
my $time = time;
my $cache = $m->cache;
$cache->set('main', 'gardenia', 0);
my $value1 = $cache->get('main', busy_lock=>'10 sec');
my $value2 = $cache->get('main');
</%init>
EOF
                      expect => <<'EOF',
undef, gardenia
EOF
                    );

#------------------------------------------------------------

    $group->add_test( name => 'busy_lock_expiration',
                      description => 'test busy_lock expiration',
                      %chi_interp_params,
                      component => <<'EOF',
<% join(', ', $value1 || 'undef', $value2 || 'undef') %>
<%init>
my $time = time;
my $cache = $m->cache;
$cache->set('main', 'gardenia', 0);
my $value1 = $cache->get('main', busy_lock=>'1 sec');
sleep(1);
my $value2 = $cache->get('main');
</%init>
EOF
                      expect => <<'EOF',
undef, undef
EOF
                    );

#------------------------------------------------------------



( run in 0.350 second using v1.01-cache-2.11-cpan-87723dcf8b7 )