1 # gitweb - simple web interface to track changes in git repositories
3 # (C) 2006, John 'Warthog9' Hawley <warthog19@eaglescrag.net>
5 # This program is licensed under the GPLv2
8 # Gitweb caching engine
11 #package gitweb::cache;
15 #my $VERSION = "0.00";
21 # Deal with cache being disabled
22 if( $cache_enable == 0 ){
23 undef $backgroundCache;
24 $fullhashpath = \
$nocachedata;
25 $fullhashbinpath = \
$nocachedatabin;
26 }elsif( $cache_enable == 1 ){
27 #obvious we are using file based caching
29 #print "Action: $action\n";
31 print "*** Warning ***: Caching enabled but cache directory does not exsist. ($cachedir)\n";
32 mkdir ("cache", 0665) || die "Cannot create cache dir - you will need to manually create";
33 print "Cache directory created successfully\n";
36 #our $local_url = "". $ENV{'HTTP_HOST'} ." + ". $ENV{'PATH_INFO'} ." + ". $ENV{'QUERY_STRING'} ."\n";
37 #print "URL: $local_url\n";
38 our $full_url = "$my_url?". $ENV{'QUERY_STRING'};
39 our $urlhash = md5_hex
($full_url);
40 our $fullhashdir = "$cachedir/". substr( $urlhash, 0, 2) ."/";
42 #if( $] < 5.010000 ) {
43 eval { mkpath
( $fullhashdir, 0777 ) };
45 die_error
(500, "Internal Server Error", "Could not create cache directory: $@");
48 # my $numdirs = make_path( $fullhashdir, { mode => 0777, error => \my $mkdirerr, } ); # This is only used with the newer File::Path
50 # my $mkdirerrmsg = "";
51 # for my $diag (@$mkdirerr) {
52 # my ($file, $message) = %$diag;
54 # $mkdirerrmsg .= "general error: $message\n";
56 # $mkdirerrmsg .= "problem unlinking $file: $message\n";
59 # die_error(500, "Internal Server Error", "Could not create cache directory | $mkdirerrmsg");
61 #} # End figuring out File::Path usage
62 $fullhashpath = "$fullhashdir/". substr( $urlhash, 2 );
63 $fullhashbinpath = "$fullhashpath.bin";
64 } # done dealing with cache enabled / disabled
66 if(! -e
"$fullhashpath" ){
67 if( ! $cache_enable || ! $cacheDoFork || ! defined(my $childPid = fork()) ){
68 cacheUpdate
($action,0);
69 cacheDisplay
($action);
70 } elsif ( $childPid == 0 ){
72 cacheUpdate
($action,1);
74 cacheWaitForUpdate
($action);
77 #if cache is out dated, update
79 open(cacheFile
, '<', "$fullhashpath");
82 $cacheTime = get_loadavg
() * 60;
83 if( $cacheTime > $maxCacheTime ){
84 $cacheTime = $maxCacheTime;
86 if( $cacheTime < $minCacheTime ){
87 $cacheTime = $minCacheTime;
89 if( (stat(_
))[9] < (time - $cacheTime) ){
90 if( ! $cacheDoFork || ! defined(my $childPid = fork()) ){
91 cacheUpdate
($action,0);
92 cacheDisplay
($action);
93 } elsif ( $childPid == 0 ){
95 #print "Running updater\n";
96 cacheUpdate
($action,1);
98 #print "Waiting for update\n";
99 cacheWaitForUpdate
($action);
102 cacheDisplay
($action);
109 # If all of the caching failes - lets go ahead and press on without it and fall back to 'default'
110 # non-caching behavior. This is the softest of the failure conditions.
112 #$actions{$action}->();
116 my ($action,$areForked) = @_;
120 if($backgroundCache){
121 open(cacheFileBG
, '>:utf8', "$fullhashpath.bg");
122 my $lockStatBG = flock(cacheFileBG
,LOCK_EX
|LOCK_NB
);
124 $lockStatus = $lockStatBG;
126 open(cacheFile
, '>:utf8', "$fullhashpath") if ($cache_enable > 0);
127 open(cacheFile
, '>:utf8', \
$fullhashpath) if ($cache_enable == 0);
128 my $lockStat = flock(cacheFile
,LOCK_EX
|LOCK_NB
);
130 $lockStatus = $lockStat;
132 #print "lock status: $lockStat\n";
135 if ($cache_enable != 0 && ! $lockStatus ){
144 $fileData = "". $actions{$action}->() ."";
146 if($backgroundCache){
147 open(cacheFile
, '>:utf8', "$fullhashpath");
148 $lockStat = flock(cacheFile
,LOCK_EX
);
159 print cacheFile
"$fileData";
161 flock(cacheFile
,LOCK_UN
);
164 if($backgroundCache){
165 flock(cacheFileBG
,LOCK_UN
);
177 sub cacheWaitForUpdate
{
183 if( $backgroundCache ){
184 if( -e
"$fullhashpath" ){
185 open(cacheFile
, '<:utf8', "$fullhashpath") if ($cache_enable > 0);
186 open(cacheFile
, '<:utf8', \
$fullhashpath) if ($cache_enable == 0);
187 $lockStat = flock(cacheFile
,LOCK_SH
|LOCK_NB
);
191 if( $lockStat && ( (stat(_
))[9] > (time - $maxCacheLife) ) ){
192 cacheDisplay
($action);
198 #our $headerRefresh = 1;
199 #print git_header_html();
210 open(cacheFile
, '<:utf8', "$fullhashpath") if ($cache_enable > 0);
211 open(cacheFile
, '<:utf8', \
$fullhashpath) if ($cache_enable == 0);
212 $lockStat = flock(cacheFile
,LOCK_SH
|LOCK_NB
);
215 $combinedLockStat = $lockStat;
216 } while ((! $combinedLockStat) && ($x < $max));
219 cacheDisplay
($action);
226 print $::cgi
->header(
232 -Pragma
=> 'no-cache',
234 -Cache_Control
=> join(
249 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www/w3.porg/TR/html4/strict.dtd">
250 <!-- git web interface version $version, (C) 2005-2006, Kay Sievers <kay.sievers\@vrfy.org>, Christian Gierke -->
251 <!-- git core binaries version $git_version -->
253 <meta http-equiv="content-type" content="$content_type; charset=utf-8"/>
254 <meta name="generator" content="gitweb/$version git/$git_version"/>
255 <meta name="robots" content="index, nofollow"/>
256 <meta http-equiv="refresh" content="0"/>
257 <title>$title</title>
262 print "Generating..";
266 open(cacheFile
, '<:utf8', "$fullhashpath") if ($cache_enable > 0);
267 open(cacheFile
, '<:utf8', \
$fullhashpath) if ($cache_enable == 0);
268 $lockStat = flock(cacheFile
,LOCK_SH
|LOCK_NB
);
270 #$lockStatbg = flock(cacheFilebg,LOCK_SH|LOCK_NB) if $backgroundCache;
271 #print "Lock State: $lockStat\n";
273 # print "Error: ". $! ."\n";
276 $combinedLockStat = $lockStat;
277 #$combinedLockStat = $lockStat & $lockStatbg if $backgroundCache;
278 } while ((! $combinedLockStat) && ($x < $max));
279 #} while ($x < $max);
281 #close(cacheFilebg) if $backgroundCache;
282 #print git_footer_html();
294 open(cacheFile
, '<:utf8', "$fullhashpath") if ($cache_enable > 0);
295 open(cacheFile
, '<:utf8', \
$fullhashpath) if ($cache_enable == 0);
296 $lockStat = flock(cacheFile
,LOCK_SH
|LOCK_NB
);
297 if ($cache_enable != 0 && ! $lockStat ){
299 cacheWaitForUpdate
($action);
302 while( <cacheFile
> ){
306 $action eq "snapshot"
308 $action eq "blob_plain"
310 open(cacheFileBin
, '<', "$fullhashbinpath");
311 binmode STDOUT
, ':raw';
312 print <cacheFileBin
>;
313 binmode STDOUT
, ':utf8'; # as set at the beginning of gitweb.cgi