+sub cachepath {$_[0] -> {cachepath}}
+sub threaddir {$_[0] -> cachepath . $_[1] -> {thread}}
+sub threadpath {$_[0] -> threaddir ($_[1]) . '/'}
+sub cachefile {$_[0] -> threadpath ($_[1]) . $_[1] -> {posting} . '.txt'}
+sub summaryfile {$_[0] -> cachepath . 'summary.bin'}
+
+### sub delete_threads #########################################################
+#
+# remove threads from cache
+#
+# Params: @threads - list of threadnumbers
+#
+# Return: Status Code (Bool)
+#
+sub delete_threads {
+ my ($self, @threads) = @_;
+ my %threads = map {$_ => 1} @threads;
+
+ $self -> mod_wrap (
+ \&r_delete_threads,
+ \%threads
+ );
+}
+sub r_delete_threads {
+ my ($self, $handle, $threads) = @_;
+ my $l = length (pack 'L' => 0);
+ my $reclen = $l << 2;
+ my $len = -s $handle;
+ my $num = int ($len / $reclen) -1;
+ my ($buf, %hash);
+ local $/;
+ local $\;
+
+ for (0..$num) {
+ seek $handle, $_ * $reclen + $l, 0 or return;
+ read ($handle, $buf, $l) == $l or return;
+ if ($threads->{unpack 'L' => $buf}) {
+ seek $handle, $_ * $reclen + $l, 0 or return;
+ print $handle pack ('L' => 0) or return;
+ }
+ }
+
+ rmtree ($self->threaddir({thread => $_}), 0, 0)
+ for (keys %$threads);
+
+ 1;
+}
+
+### sub garbage_collection #####################################################
+#
+# remove old entrys from the beginning of the cache
+#
+# Params: ~none~
+#
+# Return: ~none~
+#
+sub garbage_collection {
+ my $self = shift;
+
+ $self -> purge_wrap (
+ \&r_garbage_collection
+ );
+}
+sub r_garbage_collection {
+ my ($self, $handle, $file) = @_;
+
+ my $reclen = length (pack 'L', 0) << 2;
+ my $len = -s $handle;
+ my $num = int ($len / $reclen) -1;
+ my ($z, $buf, $h) = 0;
+ local $/;
+ local $\;
+
+ seek $handle, 0, 0 or return;
+ read ($handle, $buf, $len) or return;
+ for (0..$num) {
+ (undef, $h) = (unpack 'L2' => substr ($buf, $_ * $reclen, $reclen));
+ last if $h;
+ return unless (defined $h);
+ $z++;
+ }
+ substr ($buf, 0, $z * $reclen) = '';
+
+ seek $file, 0, 0 or return;
+ print $file $buf or return;
+
+ # looks good
+ 1;
+}