gitweb/lib - capture output directly to cache entry file
[git/jnareb-git.git] / gitweb / lib / GitwebCache / CacheOutput.pm
blob7aeb895ab91b7066590d8e45262b4061a0ee78a3
1 # gitweb - simple web interface to track changes in git repositories
3 # (C) 2010, Jakub Narebski <jnareb@gmail.com>
4 # (C) 2006, John 'Warthog9' Hawley <warthog19@eaglescrag.net>
6 # This program is licensed under the GPLv2
9 # Capturing and caching (gitweb) output
12 # Capture output, save it in cache and print it, or retrieve it from
13 # cache and print it.
15 package GitwebCache::CacheOutput;
17 use strict;
18 use warnings;
20 use File::Copy;
22 use Exporter qw(import);
23 our @EXPORT = qw(cache_output capture_stop);
24 our %EXPORT_TAGS = (all => [ @EXPORT ]);
26 # cache_output($cache, $capture, $key, $action_code);
28 # Attempts to get $key from $cache; if successful, prints the value.
29 # Otherwise, calls $action_code, capture its output using $capture,
30 # and use the captured output as the new value for $key in $cache,
31 # then print captured output.
33 # It is assumed that captured data is already converted and it is
34 # in ':raw' format (and thus restored in ':raw' from cache)
36 # default capture class (engine), if none provided
37 our $DEFAULT_CAPTURE_CLASS = 'GitwebCache::Capture::Simple';
38 sub cache_output {
39 my ($cache, $capture, $key, $code) = @_;
41 $capture = setup_capture($capture);
43 if ($cache->can('compute_fh')) {
44 my ($fh, $filename) = $cache->compute_fh($key, sub {
45 my $fh = shift;
46 $capture->capture($code, $fh);
47 });
49 if (defined $fh) {
50 binmode $fh, ':raw';
51 binmode STDOUT, ':raw';
52 copy($fh, \*STDOUT);
55 return;
58 my $data;
59 if ($cache->can('compute')) {
60 $data = cache_output_compute($cache, $capture, $key, $code);
61 } else {
62 $data = cache_output_get_set($cache, $capture, $key, $code);
65 if (defined $data) {
66 binmode STDOUT, ':raw';
67 print $data;
70 return $data;
73 # for $cache which can ->compute($key, $code)
74 sub cache_output_compute {
75 my ($cache, $capture, $key, $code) = @_;
77 my $data = $cache->compute($key, sub {
78 $capture->capture($code);
79 });
81 return $data;
84 # for $cache which can ->get($key) and ->set($key, $data)
85 sub cache_output_get_set {
86 my ($cache, $capture, $key, $code) = @_;
88 # check if data is in the cache
89 my $data = $cache->get($key);
91 # capture and cache output, if there was nothing in the cache
92 if (!defined $data) {
93 $data = $capture->capture($code);
94 $cache->set($key, $data) if defined $data;
97 return $data;
100 # capture_stop($cache, $capture);
102 # Stops capturing output; to be used in die_error, so that error pages
103 # are not cached (not captured and cached).
104 sub capture_stop {
105 my ($cache, $capture) = @_;
107 if (defined $capture) {
108 return $capture->capture_stop();
110 return;
113 # ......................................................................
114 # helper subroutines
116 # setup capture engine
117 sub setup_capture {
118 my $capture = shift;
120 $capture ||= $DEFAULT_CAPTURE_CLASS;
121 if (!ref($capture)) {
122 eval "require $capture;" or die $@;
123 $capture = $capture->new();
126 return $capture;
130 __END__
131 # end of package GitwebCache::CacheOutput