File Coverage

blib/lib/Cache/FastMmap.pm
Criterion Covered Total %
statement 273 313 87.2
branch 122 182 67.0
condition 70 96 72.9
subroutine 32 39 82.0
pod 13 16 81.2
total 510 646 78.9


line stmt bran cond sub pod time code
1             package Cache::FastMmap;
2              
3             =head1 NAME
4              
5             Cache::FastMmap - Uses an mmap'ed file to act as a shared memory interprocess cache
6              
7             =head1 SYNOPSIS
8              
9             use Cache::FastMmap;
10              
11             # Uses vaguely sane defaults
12             $Cache = Cache::FastMmap->new();
13              
14             # Uses Storable to serialize $Value to bytes for storage
15             $Cache->set($Key, $Value);
16             $Value = $Cache->get($Key);
17              
18             $Cache = Cache::FastMmap->new(serializer => '');
19              
20             # Stores stringified bytes of $Value directly
21             $Cache->set($Key, $Value);
22             $Value = $Cache->get($Key);
23              
24             =head1 ABSTRACT
25              
26             A shared memory cache through an mmap'ed file. It's core is written
27             in C for performance. It uses fcntl locking to ensure multiple
28             processes can safely access the cache at the same time. It uses
29             a basic LRU algorithm to keep the most used entries in the cache.
30              
31             =head1 DESCRIPTION
32              
33             In multi-process environments (eg mod_perl, forking daemons, etc),
34             it's common to want to cache information, but have that cache
35             shared between processes. Many solutions already exist, and may
36             suit your situation better:
37              
38             =over 4
39              
40             =item *
41              
42             L - acts as a database, data is not automatically
43             expired, slow
44              
45             =item *
46              
47             L - hash implementation is broken, data is not automatically
48             expired, slow
49              
50             =item *
51              
52             L - lots of features, slow
53              
54             =item *
55              
56             L - lots of features, VERY slow. Uses
57             IPC::ShareLite which freeze/thaws ALL data at each read/write
58              
59             =item *
60              
61             L - use your favourite RDBMS. can perform well, need a
62             DB server running. very global. socket connection latency
63              
64             =item *
65              
66             L - similar to this module, in pure perl. slows down
67             with larger pages
68              
69             =item *
70              
71             L - very fast (data ends up mostly in shared memory
72             cache) but acts as a database overall, so data is not automatically
73             expired
74              
75             =back
76              
77             In the case I was working on, I needed:
78              
79             =over 4
80              
81             =item *
82              
83             Automatic expiry and space management
84              
85             =item *
86              
87             Very fast access to lots of small items
88              
89             =item *
90              
91             The ability to fetch/store many items in one go
92              
93             =back
94              
95             Which is why I developed this module. It tries to be quite
96             efficient through a number of means:
97              
98             =over 4
99              
100             =item *
101              
102             Core code is written in C for performance
103              
104             =item *
105              
106             It uses multiple pages within a file, and uses Fcntl to only lock
107             a page at a time to reduce contention when multiple processes access
108             the cache.
109              
110             =item *
111              
112             It uses a dual level hashing system (hash to find page, then hash
113             within each page to find a slot) to make most C calls O(1) and
114             fast
115              
116             =item *
117              
118             On each C, if there are slots and page space available, only
119             the slot has to be updated and the data written at the end of the used
120             data space. If either runs out, a re-organisation of the page is
121             performed to create new slots/space which is done in an efficient way
122              
123             =back
124              
125             The class also supports read-through, and write-back or write-through
126             callbacks to access the real data if it's not in the cache, meaning that
127             code like this:
128              
129             my $Value = $Cache->get($Key);
130             if (!defined $Value) {
131             $Value = $RealDataSource->get($Key);
132             $Cache->set($Key, $Value)
133             }
134              
135             Isn't required, you instead specify in the constructor:
136              
137             Cache::FastMmap->new(
138             ...
139             context => $RealDataSourceHandle,
140             read_cb => sub { $_[0]->get($_[1]) },
141             write_cb => sub { $_[0]->set($_[1], $_[2]) },
142             );
143              
144             And then:
145              
146             my $Value = $Cache->get($Key);
147              
148             $Cache->set($Key, $NewValue);
149              
150             Will just work and will be read/written to the underlying data source as
151             needed automatically.
152              
153             =head1 PERFORMANCE
154              
155             If you're storing relatively large and complex structures into
156             the cache, then you're limited by the speed of the Storable module.
157             If you're storing simple structures, or raw data, then
158             Cache::FastMmap has noticeable performance improvements.
159              
160             See L for some
161             comparisons to other modules.
162              
163             =head1 COMPATIBILITY
164              
165             Cache::FastMmap uses mmap to map a file as the shared cache space,
166             and fcntl to do page locking. This means it should work on most
167             UNIX like operating systems.
168              
169             Ash Berlin has written a Win32 layer using MapViewOfFile et al. to
170             provide support for Win32 platform.
171              
172             =head1 MEMORY SIZE
173              
174             Because Cache::FastMmap mmap's a shared file into your processes memory
175             space, this can make each process look quite large, even though it's just
176             mmap'd memory that's shared between all processes that use the cache,
177             and may even be swapped out if the cache is getting low usage.
178              
179             However, the OS will think your process is quite large, which might
180             mean you hit some BSD::Resource or 'ulimits' you set previously that you
181             thought were sane, but aren't anymore, so be aware.
182              
183             =head1 CACHE FILES AND OS ISSUES
184              
185             Because Cache::FastMmap uses an mmap'ed file, when you put values into
186             the cache, you are actually "dirtying" pages in memory that belong to
187             the cache file. Your OS will want to write those dirty pages back to
188             the file on the actual physical disk, but the rate it does that at is
189             very OS dependent.
190              
191             In Linux, you have some control over how the OS writes those pages
192             back using a number of parameters in /proc/sys/vm
193              
194             dirty_background_ratio
195             dirty_expire_centisecs
196             dirty_ratio
197             dirty_writeback_centisecs
198              
199             How you tune these depends heavily on your setup.
200              
201             As an interesting point, if you use a highmem linux kernel, a change
202             between 2.6.16 and 2.6.20 made the kernel flush memory a LOT more.
203             There's details in this kernel mailing list thread:
204             L
205              
206             In most cases, people are not actually concerned about the persistence
207             of data in the cache, and so are happy to disable writing of any cache
208             data back to disk at all. Baically what they want is an in memory only
209             shared cache. The best way to do that is to use a "tmpfs" filesystem
210             and put all cache files on there.
211              
212             For instance, all our machines have a /tmpfs mount point that we
213             create in /etc/fstab as:
214              
215             none /tmpfs tmpfs defaults,noatime,size=1000M 0 0
216              
217             And we put all our cache files on there. The tmpfs filesystem is smart
218             enough to only use memory as required by files actually on the tmpfs,
219             so making it 1G in size doesn't actually use 1G of memory, it only uses
220             as much as the cache files we put on it. In all cases, we ensure that
221             we never run out of real memory, so the cache files effectively act
222             just as named access points to shared memory.
223              
224             Some people have suggested using anonymous mmaped memory. Unfortunately
225             we need a file descriptor to do the fcntl locking on, so we'd have
226             to create a separate file on a filesystem somewhere anyway. It seems
227             easier to just create an explicit "tmpfs" filesystem.
228              
229             =head1 PAGE SIZE AND KEY/VALUE LIMITS
230              
231             To reduce lock contention, Cache::FastMmap breaks up the file
232             into pages. When you get/set a value, it hashes the key to get a page,
233             then locks that page, and uses a hash table within the page to
234             get/store the actual key/value pair.
235              
236             One consequence of this is that you cannot store values larger than
237             a page in the cache at all. Attempting to store values larger than
238             a page size will fail (the set() function will return false).
239              
240             Also keep in mind that each page has it's own hash table, and that we
241             store the key and value data of each item. So if you are expecting to
242             store large values and/or keys in the cache, you should use page sizes
243             that are definitely larger than your largest key + value size + a few
244             kbytes for the overhead.
245              
246             =head1 USAGE
247              
248             Because the cache uses shared memory through an mmap'd file, you have
249             to make sure each process connects up to the file. There's probably
250             two main ways to do this:
251              
252             =over 4
253              
254             =item *
255              
256             Create the cache in the parent process, and then when it forks, each
257             child will inherit the same file descriptor, mmap'ed memory, etc and
258             just work. This is the recommended way. (BEWARE: This only works under
259             UNIX as Win32 has no concept of forking)
260              
261             =item *
262              
263             Explicitly connect up in each forked child to the share file. In this
264             case, make sure the file already exists and the children connect with
265             init_file => 0 to avoid deleting the cache contents and possible
266             race corruption conditions. Also be careful that multiple children
267             may race to create the file at the same time, each overwriting and
268             corrupting content. Use a separate lock file if you must to ensure
269             only one child creates the file. (This is the only possible way under
270             Win32)
271              
272             =back
273              
274             The first way is usually the easiest. If you're using the cache in a
275             Net::Server based module, you'll want to open the cache in the
276             C, because that's executed before the fork, but after
277             the process ownership has changed and any chroot has been done.
278              
279             In mod_perl, just open the cache at the global level in the appropriate
280             module, which is executed as the server is starting and before it
281             starts forking children, but you'll probably want to chmod or chown
282             the file to the permissions of the apache process.
283              
284             =head1 METHODS
285              
286             =over 4
287              
288             =cut
289              
290             # Modules/Export/XSLoader {{{
291 18     18   322537 use 5.006;
  18         80  
292 18     18   102 use strict;
  18         66  
  18         393  
293 18     18   91 use warnings;
  18         48  
  18         617  
294 18     18   9677 use bytes;
  18         228  
  18         91  
295              
296             our $VERSION = '1.46';
297              
298             require XSLoader;
299             XSLoader::load('Cache::FastMmap', $VERSION);
300              
301             # Track currently live caches so we can cleanup in END {}
302             # if we have empty_on_exit set
303             our %LiveCaches;
304              
305 18     18   1236 use constant FC_ISDIRTY => 1;
  18         40  
  18         1365  
306              
307 18     18   112 use File::Spec;
  18         33  
  18         58501  
308              
309             # }}}
310              
311             =item I
312              
313             Create a new Cache::FastMmap object.
314              
315             Basic global parameters are:
316              
317             =over 4
318              
319             =item * B
320              
321             File to mmap for sharing of data.
322             default on unix: /tmp/sharefile-$pid-$time-$random
323             default on windows: %TEMP%\sharefile-$pid-$time-$random
324              
325             =item * B
326              
327             Clear any existing values and re-initialise file. Useful to do in a
328             parent that forks off children to ensure that file is empty at the start
329             (default: 0)
330              
331             B This is quite important to do in the parent to ensure a
332             consistent file structure. The shared file is not perfectly transaction
333             safe, and so if a child is killed at the wrong instant, it might leave
334             the cache file in an inconsistent state.
335              
336             =item * B
337              
338             Use a serialization library to serialize perl data structures before
339             storing in the cache. If not set, the raw value in the variable passed
340             to set() is stored as a string. You must set this if you want to store
341             anything other than basic scalar values. Supported values are:
342              
343             '' for none
344             'storable' for 'Storable'
345             'sereal' for 'Sereal'
346             'json' for 'JSON'
347              
348             If this parameter has a value the module will attempt to load the
349             associated package and then use the API of that package to serialize data
350             before storing in the cache, and deserialize it upon retrieval from the
351             cache. (default: 'storable')
352              
353             (Note: Historically this module only supported a boolean value for the
354             `raw_values` parameter and defaulted to 0, which meant it used Storable
355             to serialze all values.)
356              
357             =item * B
358              
359             Deprecated. Use B above
360              
361             =item * B
362              
363             Compress the value (but not the key) before storing into the cache, using
364             the compression package identified by the value of the parameter. Supported
365             values are:
366              
367             'zlib' for 'Compress::Zlib'
368             'lz4' for 'Compress::LZ4'
369             'snappy' for 'Compress::Snappy'
370              
371             If this parameter has a value the module will attempt to load the
372             associated package and then use the API of that package to compress data
373             before storing in the cache, and uncompress it upon retrieval from the
374             cache. (default: undef)
375              
376             (Note: Historically this module only supported a boolean value for the
377             `compress` parameter and defaulted to use Compress::Zlib. The note for the
378             old `compress` parameter stated: "Some initial testing shows that the
379             uncompressing tends to be very fast, though the compressing can be quite
380             slow, so it's probably best to use this option only if you know values in
381             the cache are long-lived and have a high hit rate."
382              
383             Comparable test results for the other compression tools are not yet available;
384             submission of benchmarks welcome. However, the documentation for the 'Snappy'
385             library (http://google.github.io/snappy/) states: For instance, compared to
386             the fastest mode of zlib, Snappy is an order of magnitude faster for most
387             inputs, but the resulting compressed files are anywhere from 20% to 100%
388             bigger. )
389              
390             =item * B
391              
392             Deprecated. Please use B, see above.
393              
394             =item * B
395              
396             Enable some basic statistics capturing. When enabled, every read to
397             the cache is counted, and every read to the cache that finds a value
398             in the cache is also counted. You can then retrieve these values
399             via the get_statistics() call. This causes every read action to
400             do a write on a page, which can cause some more IO, so it's
401             disabled by default. (default: 0)
402              
403             =item * B
404              
405             Maximum time to hold values in the cache in seconds. A value of 0
406             means does no explicit expiry time, and values are expired only based
407             on LRU usage. Can be expressed as 1m, 1h, 1d for minutes/hours/days
408             respectively. (default: 0)
409              
410             =back
411              
412             You may specify the cache size as:
413              
414             =over 4
415              
416             =item * B
417              
418             Size of cache. Can be expresses as 1k, 1m for kilobytes or megabytes
419             respectively. Automatically guesses page size/page count values.
420              
421             =back
422              
423             Or specify explicit page size/page count values. If none of these are
424             specified, the values page_size = 64k and num_pages = 89 are used.
425              
426             =over 4
427              
428             =item * B
429              
430             Size of each page. Must be a power of 2 between 4k and 1024k. If not,
431             is rounded to the nearest value.
432              
433             =item * B
434              
435             Number of pages. Should be a prime number for best hashing
436              
437             =back
438              
439             The cache allows the use of callbacks for reading/writing data to an
440             underlying data store.
441              
442             =over 4
443              
444             =item * B
445              
446             Opaque reference passed as the first parameter to any callback function
447             if specified
448              
449             =item * B
450              
451             Callback to read data from the underlying data store. Called as:
452              
453             $read_cb->($context, $Key)
454            
455             Should return the value to use. This value will be saved in the cache
456             for future retrievals. Return undef if there is no value for the
457             given key
458              
459             =item * B
460              
461             Callback to write data to the underlying data store.
462             Called as:
463              
464             $write_cb->($context, $Key, $Value, $ExpiryTime)
465            
466             In 'write_through' mode, it's always called as soon as a I
467             is called on the Cache::FastMmap class. In 'write_back' mode, it's
468             called when a value is expunged from the cache if it's been changed
469             by a I rather than read from the underlying store with the
470             I above.
471              
472             Note: Expired items do result in the I being
473             called if 'write_back' caching is enabled and the item has been
474             changed. You can check the $ExpiryTime against C if you only
475             want to write back values which aren't expired.
476              
477             Also remember that I may be called in a different process
478             to the one that placed the data in the cache in the first place
479              
480             =item * B
481              
482             Callback to delete data from the underlying data store. Called as:
483              
484             $delete_cb->($context, $Key)
485              
486             Called as soon as I is called on the Cache::FastMmap class
487              
488             =item * B
489              
490             If set to true, then if the I is called and it returns
491             undef to say nothing was found, then that information is stored
492             in the cache, so that next time a I is called on that
493             key, undef is returned immediately rather than again calling
494             the I
495              
496             =item * B
497              
498             Either 'write_back' or 'write_through'. (default: write_through)
499              
500             =item * B
501              
502             If you're using a callback function, then normally the cache is not
503             re-enterable, and attempting to call a get/set on the cache will
504             cause an error. By setting this to one, the cache will unlock any
505             pages before calling the callback. During the unlock time, other
506             processes may change data in current cache page, causing possible
507             unexpected effects. You shouldn't set this unless you know you
508             want to be able to recall to the cache within a callback.
509             (default: 0)
510              
511             =item * B
512              
513             When you have 'write_back' mode enabled, then
514             you really want to make sure all values from the cache are expunged
515             when your program exits so any changes are written back.
516              
517             The trick is that we only want to do this in the parent process,
518             we don't want any child processes to empty the cache when they exit.
519             So if you set this, it takes the PID via $$, and only calls
520             empty in the DESTROY method if $$ matches the pid we captured
521             at the start. (default: 0)
522              
523             =item * B
524              
525             Unlink the share file when the cache is destroyed.
526              
527             As with empty_on_exit, this will only unlink the file if the
528             DESTROY occurs in the same PID that the cache was created in
529             so that any forked children don't unlink the file.
530              
531             This value defaults to 1 if the share_file specified does
532             not already exist. If the share_file specified does already
533             exist, it defaults to 0.
534              
535             =item * B
536              
537             Sets an alarm(10) before each page is locked via fcntl(F_SETLKW) to catch
538             any deadlock. This used to be the default behaviour, but it's not really
539             needed in the default case and could clobber sub-second Time::HiRes
540             alarms setup by other code. Defaults to 0.
541              
542             =back
543              
544             =cut
545             sub new {
546 8027     8027 1 154364 my $Proto = shift;
547 8027   33     32555 my $Class = ref($Proto) || $Proto;
548              
549             # If first item is a hash ref, use it as arguments
550 8027 50       45413 my %Args = ref($_[0]) eq 'HASH' ? %{shift()} : @_;
  0         0  
551              
552 8027         17035 my $Self = {};
553 8027         16362 bless ($Self, $Class);
554              
555             # Work out cache file and whether to init
556 8027         14940 my $share_file = $Args{share_file};
557 8027 50       19658 if (!$share_file) {
558 8027         84630 my $tmp_dir = File::Spec->tmpdir;
559 8027         70613 $share_file = File::Spec->catfile($tmp_dir, "sharefile");
560 8027         42732 $share_file .= "-" . $$ . "-" . time . "-" . int(rand(100000));
561             }
562 8027 50       22103 !ref($share_file) || die "share_file argument was a reference";
563 8027         19277 $Self->{share_file} = $share_file;
564 8027         14207 my $permissions = $Args{permissions};
565              
566 8027 100       18585 my $init_file = $Args{init_file} ? 1 : 0;
567 8027 50       21515 my $test_file = $Args{test_file} ? 1 : 0;
568 8027 100       16452 my $enable_stats = $Args{enable_stats} ? 1 : 0;
569 8027 50       15290 my $catch_deadlocks = $Args{catch_deadlocks} ? 1 : 0;
570              
571             # Worth out unlink default if not specified
572 8027 50       18597 if (!exists $Args{unlink_on_exit}) {
573 8027 50       374994 $Args{unlink_on_exit} = -f($share_file) ? 0 : 1;
574             }
575              
576             # Serialise stored values?
577 8027 50 66     27902 my $serializer = $Args{serializer} // ($Args{raw_values} ? '' : 'storable');
578              
579 8027 100       17875 if ($serializer) {
580 5 50       25 if ($serializer eq 'storable') {
    0          
    0          
581 5 50       343 eval "require Storable;"
582             || die "Could not load serialization package: Storable : $@";
583 5         11445 $Self->{serialize} = Storable->can("freeze");
584 5         31 $Self->{deserialize} = Storable->can("thaw");
585             } elsif ($serializer eq 'sereal') {
586 0 0       0 eval "require Sereal::Encoder; require Sereal::Decoder;"
587             || die "Could not load serialization package: Sereal : $@";
588 0         0 my $SerealEnc = Sereal::Encoder->new();
589 0         0 my $SerealDec = Sereal::Decoder->new();
590 0     0   0 $Self->{serialize} = sub { $SerealEnc->encode(@_); };
  0         0  
591 0     0   0 $Self->{deserialize} = sub { $SerealDec->decode(@_); };
  0         0  
592             } elsif ($serializer eq 'json') {
593 0 0       0 eval "require JSON;"
594             || die "Could not load serialization package: JSON : $@";
595 0         0 my $JSON = JSON->new->utf8->allow_nonref;
596 0     0   0 $Self->{serialize} = sub { $JSON->encode(${$_[0]}); };
  0         0  
  0         0  
597 0     0   0 $Self->{deserialize} = sub { \$JSON->decode($_[0]); };
  0         0  
598             } else {
599 0         0 die "Unrecognized value >$serializer< for `serializer` parameter";
600             }
601             }
602              
603             # Compress stored values?
604 8027 100 100     35583 my $compressor = $Args{compressor} // ($Args{compress} ? 'zlib' : 0);
605              
606 8027         32686 my %known_compressors = (
607             zlib => 'Compress::Zlib',
608             lz4 => 'Compress::LZ4',
609             snappy => 'Compress::Snappy',
610             );
611              
612 8027 100       18544 if ( $compressor ) {
613 4   50     17 my $compressor_module = $known_compressors{$compressor}
614             || die "Unrecognized value >$compressor< for `compressor` parameter";
615              
616 4 50       271 if ( ! eval "require $compressor_module;" ) {
617 0         0 die "Could not load compression package: $compressor_module : $@";
618             } else {
619             # LZ4 and Snappy use same API
620 4 50 33     42 if ($compressor_module eq 'Compress::LZ4' || $compressor_module eq 'Compress::Snappy') {
    50          
621 0         0 $Self->{compress} = $compressor_module->can("compress");
622 0         0 $Self->{uncompress} = $compressor_module->can("uncompress");
623             } elsif ($compressor_module eq 'Compress::Zlib') {
624 4         36 $Self->{compress} = $compressor_module->can("memGzip");
625             # (gunzip from tmp var: https://rt.cpan.org/Ticket/Display.html?id=72945)
626 4         23 my $uncompress = $compressor_module->can("memGunzip");
627 4     2   23 $Self->{uncompress} = sub { &$uncompress(my $Tmp = shift) };
  2         11  
628             }
629             }
630             }
631              
632             # If using empty_on_exit, need to track used caches
633 8027   100     30202 my $empty_on_exit = $Self->{empty_on_exit} = int($Args{empty_on_exit} || 0);
634              
635             # Need Scalar::Util::weaken to track open caches
636 8027 100       18884 if ($empty_on_exit) {
637 1 50   1   63 eval "use Scalar::Util qw(weaken); 1;"
  1         6  
  1         2  
  1         46  
638             || die "Could not load Scalar::Util module: $@";
639             }
640              
641             # Work out expiry time in seconds
642 8027         26566 my $expire_time = $Self->{expire_time} = parse_expire_time($Args{expire_time});
643              
644             # Function rounds to the nearest power of 2
645 8027     8027 0 30861 sub RoundPow2 { return int(2 ** int(log($_[0])/log(2)) + 0.1); }
646              
647             # Work out cache size
648 8027         20790 my ($cache_size, $num_pages, $page_size);
649              
650 8027         18772 my %Sizes = (k => 1024, m => 1024*1024);
651 8027 50       17089 if ($cache_size = $Args{cache_size}) {
652 0 0       0 $cache_size *= $Sizes{lc($1)} if $cache_size =~ s/([km])$//i;
653              
654 0 0       0 if ($num_pages = $Args{num_pages}) {
655 0         0 $page_size = RoundPow2($cache_size / $num_pages);
656 0 0       0 $page_size = 4096 if $page_size < 4096;
657              
658             } else {
659 0   0     0 $page_size = $Args{page_size} || 65536;
660 0 0       0 $page_size *= $Sizes{lc($1)} if $page_size =~ s/([km])$//i;
661 0 0       0 $page_size = 4096 if $page_size < 4096;
662              
663             # Increase num_pages till we exceed
664 0         0 $num_pages = 89;
665 0 0       0 if ($num_pages * $page_size <= $cache_size) {
666 0         0 while ($num_pages * $page_size <= $cache_size) {
667 0         0 $num_pages = $num_pages * 2 + 1;
668             }
669             } else {
670 0         0 while ($num_pages * $page_size > $cache_size) {
671 0         0 $num_pages = int(($num_pages-1) / 2);
672             }
673 0         0 $num_pages = $num_pages * 2 + 1;
674             }
675              
676             }
677              
678             } else {
679 8027         18162 ($num_pages, $page_size) = @Args{qw(num_pages page_size)};
680 8027   100     18942 $num_pages ||= 89;
681 8027   100     17315 $page_size ||= 65536;
682 8027 50       36126 $page_size *= $Sizes{lc($1)} if $page_size =~ s/([km])$//i;
683 8027         18991 $page_size = RoundPow2($page_size);
684             }
685              
686 8027         14703 $cache_size = $num_pages * $page_size;
687 8027         24320 @$Self{qw(cache_size num_pages page_size)}
688             = ($cache_size, $num_pages, $page_size);
689              
690             # Number of slots to start in each page
691 8027   50     42792 my $start_slots = int($Args{start_slots} || 0) || 89;
692              
693             # Save read through/write back/write through details
694 8027   100     22590 my $write_back = ($Args{write_action} || 'write_through') eq 'write_back';
695             @$Self{qw(context read_cb write_cb delete_cb)}
696 8027         28839 = @Args{qw(context read_cb write_cb delete_cb)};
697             @$Self{qw(cache_not_found allow_recursive write_back)}
698 8027         21131 = (@Args{qw(cache_not_found allow_recursive)}, $write_back);
699             @$Self{qw(unlink_on_exit enable_stats)}
700 8027         18801 = (@Args{qw(unlink_on_exit)}, $enable_stats);
701              
702             # Save pid
703 8027         26776 $Self->{pid} = $$;
704              
705             # Initialise C cache code
706 8027         23797 my $Cache = fc_new();
707              
708 8027         15160 $Self->{Cache} = $Cache;
709              
710             # Setup cache parameters
711 8027         28046 fc_set_param($Cache, 'init_file', $init_file);
712 8027         19586 fc_set_param($Cache, 'test_file', $test_file);
713 8027         20699 fc_set_param($Cache, 'page_size', $page_size);
714 8027         19589 fc_set_param($Cache, 'num_pages', $num_pages);
715 8027         18453 fc_set_param($Cache, 'expire_time', $expire_time);
716 8027         18673 fc_set_param($Cache, 'share_file', $share_file);
717 8027 50       18557 fc_set_param($Cache, 'permissions', $permissions) if defined $permissions;
718 8027         20331 fc_set_param($Cache, 'start_slots', $start_slots);
719 8027         18883 fc_set_param($Cache, 'catch_deadlocks', $catch_deadlocks);
720 8027         19212 fc_set_param($Cache, 'enable_stats', $enable_stats);
721              
722             # And initialise it
723 8027         3065114 fc_init($Cache);
724              
725             # Track cache if need to empty on exit
726 8027 100       40171 weaken($LiveCaches{ref($Self)} = $Self)
727             if $empty_on_exit;
728              
729             # All done, return PERL hash ref as class
730 8027         73500 return $Self;
731             }
732              
733             =item I
734              
735             Search cache for given Key. Returns undef if not found. If
736             I specified and not found, calls the callback to try
737             and find the value for the key, and if found (or 'cache_not_found'
738             is set), stores it into the cache and returns the found value.
739              
740             I<%Options> is optional, and is used by get_and_set() to control
741             the locking behaviour. For now, you should probably ignore it
742             unless you read the code to understand how it works
743              
744             =cut
745             sub get {
746 185900     185900 1 1970210 my ($Self, $Cache) = ($_[0], $_[0]->{Cache});
747              
748             # Hash value, lock page, read result
749 185900         472773 my ($HashPage, $HashSlot) = fc_hash($Cache, $_[1]);
750 185900         397417 my $Unlock = $Self->_lock_page($HashPage);
751 185899         661111 my ($Val, $Flags, $Found) = fc_read($Cache, $HashSlot, $_[1]);
752              
753             # Value not found, check underlying data store
754 185899 100 100     583093 if (!$Found && (my $read_cb = $Self->{read_cb})) {
755              
756             # Callback to read from underlying data store
757             # (unlock page first if we allow recursive calls
758 21262 100       45417 $Unlock = undef if $Self->{allow_recursive};
759 21262         32466 $Val = eval { $read_cb->($Self->{context}, $_[1]); };
  21262         44329  
760 21262         79578 my $Err = $@;
761 21262 100       44843 $Unlock = $Self->_lock_page($HashPage) if $Self->{allow_recursive};
762              
763             # Pass on any error
764 21262 100       41971 if ($Err) {
765 1         7 die $Err;
766             }
767              
768             # If we found it, or want to cache not-found, store back into our cache
769 21261 100 100     60871 if (defined $Val || $Self->{cache_not_found}) {
770              
771             # Are we doing writeback's? If so, need to mark as dirty in cache
772 12923         19455 my $write_back = $Self->{write_back};
773              
774 12923 100       25811 $Val = $Self->{serialize}(\$Val) if $Self->{serialize};
775 12923 50       24035 $Val = $Self->{compress}($Val) if $Self->{compress};
776              
777             # Get key/value len (we've got 'use bytes'), and do expunge check to
778             # create space if needed
779 12923 100       26644 my $KVLen = length($_[1]) + (defined($Val) ? length($Val) : 0);
780 12923         29079 $Self->_expunge_page(2, 1, $KVLen);
781              
782 12923         36739 fc_write($Cache, $HashSlot, $_[1], $Val, -1, 0);
783             }
784             }
785              
786             # Unlock page and return any found value
787             # Unlock is done only if we're not in the middle of a get_set() operation.
788 185898   66     452928 my $SkipUnlock = $_[2] && $_[2]->{skip_unlock};
789 185898 100       401525 $Unlock = undef unless $SkipUnlock;
790              
791             # If not using raw values, use thaw() to turn data back into object
792 185898 100 100     429097 $Val = $Self->{uncompress}($Val) if defined($Val) && $Self->{compress};
793 185898 100 100     674744 $Val = ${$Self->{deserialize}($Val)} if defined($Val) && $Self->{deserialize};
  99309         239253  
794              
795             # If explicitly asked to skip unlocking, we return the reference to the unlocker
796 185898 100       1765114 return ($Val, $Unlock) if $SkipUnlock;
797              
798 165889         358416 return $Val;
799             }
800              
801             =item I
802              
803             Store specified key/value pair into cache
804              
805             I<%Options> is optional, and is used by get_and_set() to control
806             the locking behaviour. For now, you should probably ignore it
807             unless you read the code to understand how it works
808              
809             This method returns true if the value was stored in the cache,
810             false otherwise. See the PAGE SIZE AND KEY/VALUE LIMITS section
811             for more details.
812              
813             =cut
814             sub set {
815 90968     90968 1 13840965 my ($Self, $Cache) = ($_[0], $_[0]->{Cache});
816              
817 90968 100       214059 my $Val = $Self->{serialize} ? $Self->{serialize}(\$_[2]) : $_[2];
818 90968 100       315628 $Val = $Self->{compress}($Val) if $Self->{compress};
819              
820             # Get opts, make compatible with Cache::Cache interface
821 90968 100       196641 my $Opts = defined($_[3]) ? (ref($_[3]) ? $_[3] : { expire_time => $_[3] }) : undef;
    100          
822 90968 100 100     256768 my $expire_seconds = defined($Opts && $Opts->{expire_time}) ? parse_expire_time($Opts->{expire_time}) : -1;
823              
824             # Hash value, lock page
825 90968         245217 my ($HashPage, $HashSlot) = fc_hash($Cache, $_[1]);
826              
827             # If skip_lock is passed, it's a *reference* to an existing lock we
828             # have to take and delete so we can cleanup below before calling
829             # the callback
830 90968   100     225763 my $Unlock = $Opts && $Opts->{skip_lock};
831 90968 100       172519 if ($Unlock) {
832 15009         36310 ($Unlock, $$Unlock) = ($$Unlock, undef);
833             } else {
834 75959         145994 $Unlock = $Self->_lock_page($HashPage);
835             }
836              
837             # Are we doing writeback's? If so, need to mark as dirty in cache
838 90968         169157 my $write_back = $Self->{write_back};
839              
840             # Get key/value len (we've got 'use bytes'), and do expunge check to
841             # create space if needed
842 90968 100       209318 my $KVLen = length($_[1]) + (defined($Val) ? length($Val) : 0);
843 90968         227245 $Self->_expunge_page(2, 1, $KVLen);
844              
845             # Now store into cache
846 90968 100       343812 my $DidStore = fc_write($Cache, $HashSlot, $_[1], $Val, $expire_seconds, $write_back ? FC_ISDIRTY : 0);
847              
848             # Unlock page
849 90968         156125 $Unlock = undef;
850              
851             # If we're doing write-through, or write-back and didn't get into cache,
852             # write back to the underlying store
853 90968 100 66     211213 if ((!$write_back || !$DidStore) && (my $write_cb = $Self->{write_cb})) {
      100        
854 3000         5078 eval { $write_cb->($Self->{context}, $_[1], $_[2]); };
  3000         7203  
855             }
856              
857 90968         234529 return $DidStore;
858             }
859              
860             =item I
861              
862             Atomically retrieve and set the value of a Key.
863              
864             The page is locked while retrieving the $Key and is unlocked only after
865             the value is set, thus guaranteeing the value does not change between
866             the get and set operations.
867              
868             $Sub is a reference to a subroutine that is called to calculate the
869             new value to store. $Sub gets $Key and the current value
870             as parameters, and
871             should return the new value to set in the cache for the given $Key.
872              
873             If the subroutine returns an empty list, no value is stored back
874             in the cache. This avoids updating the expiry time on an entry
875             if you want to do a "get if in cache, store if not present" type
876             callback.
877              
878             For example, to atomically increment a value in the cache, you
879             can just use:
880              
881             $Cache->get_and_set($Key, sub { return ++$_[1]; });
882              
883             In scalar context, the return value from this function is the *new* value
884             stored back into the cache.
885              
886             In list context, a two item array is returned; the new value stored
887             back into the cache and a boolean that's true if the value was stored
888             in the cache, false otherwise. See the PAGE SIZE AND KEY/VALUE LIMITS
889             section for more details.
890              
891             Notes:
892              
893             =over 4
894              
895             =item *
896              
897             Do not perform any get/set operations from the callback sub, as these
898             operations lock the page and you may end up with a dead lock!
899              
900             =item *
901              
902             If your sub does a die/throws an exception, the page will correctly
903             be unlocked (1.15 onwards)
904              
905             =back
906              
907             =cut
908             sub get_and_set {
909 15009     15009 1 135928 my ($Self, $Cache) = ($_[0], $_[0]->{Cache});
910              
911 15009         54453 my ($Value, $Unlock) = $Self->get($_[1], { skip_unlock => 1 });
912              
913             # If this throws an error, $Unlock ref will still unlock page
914 15009         66084 my @NewValue = $_[2]->($_[1], $Value);
915              
916 15009         84116 my $DidStore = 0;
917 15009 50       44064 if (@NewValue) {
918 15009         32979 ($Value) = @NewValue;
919 15009         63630 $DidStore = $Self->set($_[1], $Value, { skip_lock => \$Unlock });
920             }
921              
922 15009 100       85504 return wantarray ? ($Value, $DidStore) : $Value;
923             }
924              
925             =item I
926              
927             Delete the given key from the cache
928              
929             I<%Options> is optional, and is used by get_and_remove() to control
930             the locking behaviour. For now, you should probably ignore it
931             unless you read the code to understand how it works
932              
933             =cut
934             sub remove {
935 11301     11301 1 52799 my ($Self, $Cache) = ($_[0], $_[0]->{Cache});
936              
937             # Hash value, lock page, read result
938 11301         33652 my ($HashPage, $HashSlot) = fc_hash($Cache, $_[1]);
939              
940             # If skip_lock is passed, it's a *reference* to an existing lock we
941             # have to take and delete so we can cleanup below before calling
942             # the callback
943 11301   66     37352 my $Unlock = $_[2] && $_[2]->{skip_lock};
944 11301 100       26777 if ($Unlock) {
945 5000         10406 ($Unlock, $$Unlock) = ($$Unlock, undef);
946             } else {
947 6301         15677 $Unlock = $Self->_lock_page($HashPage);
948             }
949              
950 11301         41331 my ($DidDel, $Flags) = fc_delete($Cache, $HashSlot, $_[1]);
951 11301         22642 $Unlock = undef;
952              
953             # If we deleted from the cache, and it's not dirty, also delete
954             # from underlying store
955 11301 100 66     30224 if ((!$DidDel || ($DidDel && !($Flags & FC_ISDIRTY)))
      66        
956             && (my $delete_cb = $Self->{delete_cb})) {
957 301         487 eval { $delete_cb->($Self->{context}, $_[1]); };
  301         587  
958             }
959            
960 11301         31878 return $DidDel;
961             }
962              
963             =item I
964              
965             Atomically retrieve value of a Key while removing it from the cache.
966              
967             The page is locked while retrieving the $Key and is unlocked only after
968             the value is removed, thus guaranteeing the value stored by someone else
969             isn't removed by us.
970              
971             =cut
972             sub get_and_remove {
973 5000     5000 1 21106 my ($Self, $Cache) = ($_[0], $_[0]->{Cache});
974              
975 5000         15962 my ($Value, $Unlock) = $Self->get($_[1], { skip_unlock => 1 });
976 5000         19524 my $DidDel = $Self->remove($_[1], { skip_lock => \$Unlock });
977 5000 50       21151 return wantarray ? ($Value, $DidDel) : $Value;
978             }
979              
980             =item I
981              
982             Clear all items from the cache
983              
984             Note: If you're using callbacks, this has no effect
985             on items in the underlying data store. No delete
986             callbacks are made
987              
988             =cut
989             sub clear {
990 4     4 1 4010 my $Self = shift;
991 4         24 $Self->_expunge_all(1, 0);
992             }
993              
994             =item I
995              
996             Clear all expired items from the cache
997              
998             Note: If you're using callbacks, this has no effect
999             on items in the underlying data store. No delete
1000             callbacks are made, and no write callbacks are made
1001             for the expired data
1002              
1003             =cut
1004             sub purge {
1005 0     0 1 0 my $Self = shift;
1006 0         0 $Self->_expunge_all(0, 0);
1007             }
1008              
1009             =item I
1010              
1011             Empty all items from the cache, or if $OnlyExpired is
1012             true, only expired items.
1013              
1014             Note: If 'write_back' mode is enabled, any changed items
1015             are written back to the underlying store. Expired items are
1016             written back to the underlying store as well.
1017              
1018             =cut
1019             sub empty {
1020 5     5 1 2040 my $Self = shift;
1021 5 50       53 $Self->_expunge_all($_[0] ? 0 : 1, 1);
1022             }
1023              
1024             =item I
1025              
1026             Get a list of keys/values held in the cache. May immediately be out of
1027             date because of the shared access nature of the cache
1028              
1029             If $Mode == 0, an array of keys is returned
1030              
1031             If $Mode == 1, then an array of hashrefs, with 'key',
1032             'last_access', 'expire_time' and 'flags' keys is returned
1033              
1034             If $Mode == 2, then hashrefs also contain 'value' key
1035              
1036             =cut
1037             sub get_keys {
1038 615     615 1 1842908 my ($Self, $Cache) = ($_[0], $_[0]->{Cache});
1039              
1040 615   100     3319 my $Mode = $_[1] || 0;
1041 615         1932 my ($Uncompress, $Deserialize) = @$Self{qw(uncompress deserialize)};
1042              
1043 615 100 33     4298076 return fc_get_keys($Cache, $Mode)
      66        
      100        
1044             if $Mode <= 1 || ($Mode == 2 && !$Uncompress && !$Deserialize);
1045              
1046             # If we're getting values as well, and they're not raw, unfreeze them
1047 1         147 my @Details = fc_get_keys($Cache, 2);
1048              
1049 1         5 for (@Details) {
1050 2         4 my $Val = $_->{value};
1051 2 50       6 if (defined $Val) {
1052 2 50       5 $Val = $Uncompress->($Val) if $Uncompress;
1053 2 50       5 $Val = ${$Deserialize->($Val)} if $Deserialize;
  2         6  
1054 2         31 $_->{value} = $Val;
1055             }
1056             }
1057 1         4 return @Details;
1058             }
1059              
1060             =item I
1061              
1062             Returns a two value list of (nreads, nreadhits). This
1063             only works if you passed enable_stats in the constructor
1064              
1065             nreads is the total number of read attempts done on the
1066             cache since it was created
1067              
1068             nreadhits is the total number of read attempts done on
1069             the cache since it was created that found the key/value
1070             in the cache
1071              
1072             If $Clear is true, the values are reset immediately after
1073             they are retrieved
1074              
1075             =cut
1076             sub get_statistics {
1077 3     3 1 6499 my ($Self, $Cache) = ($_[0], $_[0]->{Cache});
1078 3         13 my $Clear = $_[1];
1079              
1080 3         12 my ($NReads, $NReadHits) = (0, 0);
1081 3         22 for (0 .. $Self->{num_pages}-1) {
1082 267         1062 my $Unlock = $Self->_lock_page($_);
1083 267         1152 my ($PNReads, $PNReadHits) = fc_get_page_details($Cache);
1084 267         662 $NReads += $PNReads;
1085 267         523 $NReadHits += $PNReadHits;
1086 267 100       1007 fc_reset_page_details($Cache) if $Clear;
1087 267         1098 $Unlock = undef;
1088             }
1089 3         25 return ($NReads, $NReadHits);
1090             }
1091              
1092             =item I
1093              
1094             The two multi_xxx routines act a bit differently to the
1095             other routines. With the multi_get, you pass a separate
1096             PageKey value and then multiple keys. The PageKey value
1097             is hashed, and that page locked. Then that page is
1098             searched for each key. It returns a hash ref of
1099             Key => Value items found in that page in the cache.
1100              
1101             The main advantage of this is just a speed one, if you
1102             happen to need to search for a lot of items on each call.
1103              
1104             For instance, say you have users and a bunch of pieces
1105             of separate information for each user. On a particular
1106             run, you need to retrieve a sub-set of that information
1107             for a user. You could do lots of get() calls, or you
1108             could use the 'username' as the page key, and just
1109             use one multi_get() and multi_set() call instead.
1110              
1111             A couple of things to note:
1112              
1113             =over 4
1114              
1115             =item 1.
1116              
1117             This makes multi_get()/multi_set() and get()/set()
1118             incompatible. Don't mix calls to the two, because
1119             you won't find the data you're expecting
1120              
1121             =item 2.
1122              
1123             The writeback and callback modes of operation do
1124             not work with multi_get()/multi_set(). Don't attempt
1125             to use them together.
1126              
1127             =back
1128              
1129             =cut
1130             sub multi_get {
1131 2     2 1 1012 my ($Self, $Cache) = ($_[0], $_[0]->{Cache});
1132              
1133             # Hash value page key, lock page
1134 2         6 my ($HashPage, $HashSlot) = fc_hash($Cache, $_[1]);
1135 2         7 my $Unlock = $Self->_lock_page($HashPage);
1136              
1137             # For each key to find
1138 2         5 my ($Keys, %KVs) = ($_[2]);
1139 2         5 for (@$Keys) {
1140              
1141             # Hash key to get slot in this page and read
1142 4         10 my $FinalKey = "$_[1]-$_";
1143 4         12 (undef, $HashSlot) = fc_hash($Cache, $FinalKey);
1144 4         15 my ($Val, $Flags, $Found) = fc_read($Cache, $HashSlot, $FinalKey);
1145 4 50       12 next unless $Found;
1146              
1147             # If not using raw values, use thaw() to turn data back into object
1148 4 50 33     21 $Val = $Self->{uncompress}($Val) if defined($Val) && $Self->{compress};
1149 4 50 33     19 $Val = ${$Self->{deserialize}($Val)} if defined($Val) && $Self->{deserialize};
  0         0  
1150              
1151             # Save to return
1152 4         12 $KVs{$_} = $Val;
1153             }
1154              
1155             # Unlock page and return any found value
1156 2         4 $Unlock = undef;
1157              
1158 2         8 return \%KVs;
1159             }
1160              
1161             =item I $Value1, $Key2 => $Value2, ... }, [ \%Options ])>
1162              
1163             Store specified key/value pair into cache
1164              
1165             =cut
1166             sub multi_set {
1167 2     2 1 2569 my ($Self, $Cache) = ($_[0], $_[0]->{Cache});
1168              
1169             # Get opts, make compatible with Cache::Cache interface
1170 2 0       8 my $Opts = defined($_[3]) ? (ref($_[3]) ? $_[3] : { expire_time => $_[3] }) : undef;
    50          
1171 2 50 33     9 my $expire_seconds = defined($Opts && $Opts->{expire_time}) ? parse_expire_time($Opts->{expire_time}) : -1;
1172              
1173             # Hash page key value, lock page
1174 2         7 my ($HashPage, $HashSlot) = fc_hash($Cache, $_[1]);
1175 2         6 my $Unlock = $Self->_lock_page($HashPage);
1176              
1177             # Loop over each key/value storing into this page
1178 2         3 my $KVs = $_[2];
1179 2         10 while (my ($Key, $Val) = each %$KVs) {
1180              
1181 4 50       11 $Val = $Self->{serialize}(\$Val) if $Self->{serialize};
1182 4 50       9 $Val = $Self->{compress}($Val) if $Self->{compress};
1183              
1184             # Get key/value len (we've got 'use bytes'), and do expunge check to
1185             # create space if needed
1186 4         7 my $FinalKey = "$_[1]-$Key";
1187 4         8 my $KVLen = length($FinalKey) + length($Val);
1188 4         9 $Self->_expunge_page(2, 1, $KVLen);
1189              
1190             # Now hash key and store into page
1191 4         9 (undef, $HashSlot) = fc_hash($Cache, $FinalKey);
1192 4         18 my $DidStore = fc_write($Cache, $HashSlot, $FinalKey, $Val, $expire_seconds, 0);
1193             }
1194              
1195             # Unlock page
1196 2         5 $Unlock = undef;
1197              
1198 2         5 return 1;
1199             }
1200              
1201             =back
1202              
1203             =cut
1204              
1205             =head1 INTERNAL METHODS
1206              
1207             =over 4
1208              
1209             =cut
1210              
1211             =item I<_expunge_all($Mode, $WB)>
1212              
1213             Expunge all items from the cache
1214              
1215             Expunged items (that have not expired) are written
1216             back to the underlying store if write_back is enabled
1217              
1218             =cut
1219             sub _expunge_all {
1220 9     9   49 my ($Self, $Cache, $Mode, $WB) = ($_[0], $_[0]->{Cache}, $_[1], $_[2]);
1221              
1222             # Repeat expunge for each page
1223 9         57 for (0 .. $Self->{num_pages}-1) {
1224 557         1362 my $Unlock = $Self->_lock_page($_);
1225 557         1691 $Self->_expunge_page($Mode, $WB, -1);
1226 557         1918 $Unlock = undef;
1227             }
1228              
1229             }
1230              
1231             =item I<_expunge_page($Mode, $WB, $Len)>
1232              
1233             Expunge items from the current page to make space for
1234             $Len bytes key/value items
1235              
1236             Expunged items (that have not expired) are written
1237             back to the underlying store if write_back is enabled
1238              
1239             =cut
1240             sub _expunge_page {
1241 104452     104452   257042 my ($Self, $Cache, $Mode, $WB, $Len) = ($_[0], $_[0]->{Cache}, @_[1 .. 3]);
1242              
1243             # If writeback mode, need to get expunged items to write back
1244 104452 100 100     358082 my $write_cb = $Self->{write_back} && $WB ? $Self->{write_cb} : undef;
1245              
1246 104452 100       420816 my @WBItems = fc_expunge($Cache, $Mode, $write_cb ? 1 : 0, $Len);
1247              
1248 104452         208223 my ($Uncompress, $Deserialize) = @$Self{qw(uncompress deserialize)};
1249              
1250 104452         240517 for (@WBItems) {
1251 40643 100       133351 next if !($_->{flags} & FC_ISDIRTY);
1252              
1253 32687         50858 my $Val = $_->{value};
1254 32687 100       64778 if (defined $Val) {
1255 29429 50       56840 $Val = $Uncompress->($Val) if $Uncompress;
1256 29429 100       56158 $Val = ${$Deserialize->($Val)} if $Deserialize;
  2         7  
1257             }
1258 32687         46475 eval { $write_cb->($Self->{context}, $_->{key}, $Val, $_->{expire_time}); };
  32687         66485  
1259             }
1260             }
1261              
1262             =item I<_lock_page($Page)>
1263              
1264             Lock a given page in the cache, and return an object
1265             reference that when DESTROYed, unlocks the page
1266              
1267             =cut
1268             sub _lock_page {
1269 268989     268989   491336 my ($Self, $Cache) = ($_[0], $_[0]->{Cache});
1270             my $Unlock = Cache::FastMmap::OnLeave->new(sub {
1271 268989 100   268989   1703191 fc_unlock($Cache) if fc_is_locked($Cache);
1272 268989         970392 });
1273 268989         3365773 fc_lock($Cache, $_[1]);
1274 268988         549396 return $Unlock;
1275             }
1276              
1277             sub parse_expire_time {
1278 8044   100 8044 0 35100 my $expire_time = shift || '';
1279 8044 100       21601 return 1 if $expire_time eq 'now';
1280 8042 100       19013 return 0 if $expire_time eq 'never';
1281 8040         26165 my %Times = ('' => 1, s => 1, m => 60, h => 60*60, d => 24*60*60, w => 7*24*60*60);
1282 8040 100       32670 return $expire_time =~ /^(\d+)\s*([mhdws]?)/i ? $1 * $Times{lc($2)} : 0;
1283             }
1284              
1285             sub cleanup {
1286 8024     8024 0 23914 my ($Self, $Cache) = ($_[0], $_[0]->{Cache});
1287              
1288             # Avoid potential double cleanup
1289 8024 50       19909 return if $Self->{cleaned};
1290 8024         15375 $Self->{cleaned} = 1;
1291              
1292             # Expunge all entries on exit if requested and in parent process
1293 8024 50 66     21712 if ($Self->{empty_on_exit} && $Cache && $Self->{pid} == $$) {
      66        
1294 1         5 $Self->empty();
1295             }
1296              
1297 8024 50       19758 if ($Cache) {
1298 8024         71225 fc_close($Cache);
1299 8024         15257 $Cache = undef;
1300 8024         17755 delete $Self->{Cache};
1301             }
1302              
1303             unlink($Self->{share_file})
1304 8024 100 66     936258 if $Self->{unlink_on_exit} && $Self->{pid} == $$;
1305              
1306             }
1307              
1308             sub DESTROY {
1309 8024     8024   84010 my $Self = shift;
1310 8024         23223 $Self->cleanup();
1311 8024 100       92247 delete $LiveCaches{ref($Self)} if $Self->{empty_on_exit};
1312             }
1313              
1314             sub END {
1315 18     18   43533 while (my (undef, $Self) = each %LiveCaches) {
1316             # Weak reference, might be undef already
1317 0 0       0 $Self->cleanup() if $Self;
1318             }
1319 18         175 %LiveCaches = ();
1320             }
1321              
1322             sub CLONE {
1323 0     0   0 die "Cache::FastMmap does not support threads sorry";
1324             }
1325              
1326             1;
1327              
1328             package Cache::FastMmap::OnLeave;
1329 18     18   186 use strict;
  18         52  
  18         2312  
1330              
1331             sub new {
1332 268989     268989   482987 my $Class = shift;
1333 268989         419668 my $Ref = \$_[0];
1334 268989         495265 bless $Ref, $Class;
1335 268989         495119 return $Ref;
1336             }
1337              
1338             sub disable {
1339 0     0   0 ${$_[0]} = undef;
  0         0  
1340             }
1341              
1342             sub DESTROY {
1343 268989     268989   451874 my $e = $@; # Save errors from code calling us
1344 268989         412365 eval {
1345              
1346 268989         405962 my $Ref = shift;
1347 268989 50       717102 $$Ref->() if $$Ref;
1348              
1349             };
1350             # $e .= " (in cleanup) $@" if $@;
1351 268989         1663066 $@ = $e;
1352             }
1353              
1354             1;
1355              
1356             __END__