File Coverage

blib/lib/Mail/SpamAssassin/BayesStore.pm
Criterion Covered Total %
statement 39 187 20.8
branch 4 56 7.1
condition 3 32 9.3
subroutine 8 43 18.6
pod 38 39 97.4
total 92 357 25.7


line stmt bran cond sub pod time code
1             # <@LICENSE>
2             # Licensed to the Apache Software Foundation (ASF) under one or more
3             # contributor license agreements. See the NOTICE file distributed with
4             # this work for additional information regarding copyright ownership.
5             # The ASF licenses this file to you under the Apache License, Version 2.0
6             # (the "License"); you may not use this file except in compliance with
7             # the License. You may obtain a copy of the License at:
8             #
9             # http://www.apache.org/licenses/LICENSE-2.0
10             #
11             # Unless required by applicable law or agreed to in writing, software
12             # distributed under the License is distributed on an "AS IS" BASIS,
13             # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14             # See the License for the specific language governing permissions and
15             # limitations under the License.
16             # </@LICENSE>
17              
18             =head1 NAME
19              
20             Mail::SpamAssassin::BayesStore - Storage Module for default Bayes classifier
21              
22             =head1 DESCRIPTION
23              
24             This is the public API for the Bayesian store methods. Any implementation of
25             the storage module for the default Bayes classifier must implement these methods.
26              
27             =cut
28              
29              
30             use strict;
31 21     21   129 use warnings;
  21         40  
  21         563  
32 21     21   477 # use bytes;
  21         572  
  21         530  
33             use re 'taint';
34 21     21   107 use Mail::SpamAssassin::Logger;
  21         38  
  21         512  
35 21     21   101  
  21         396  
  21         43216  
36             # TODO: if we ever get tuits, it'd be good to make these POD
37             # method docs more perlish... hardly a biggie.
38              
39             =head1 METHODS
40              
41             =over 4
42              
43             =item new
44              
45             public class (Mail::SpamAssassin::BayesStore) new (Mail::SpamAssassin::Plugin::Bayes $bayes)
46              
47             Description:
48             This method creates a new instance of the Mail::SpamAssassin::BayesStore
49             object. You must pass in an instance of the Mail::SpamAssassin::Plugin::Bayes
50             object, which is stashed for use throughout the module.
51              
52             =cut
53              
54             my ($class, $bayes) = @_;
55              
56 63     63 1 195 $class = ref($class) || $class;
57              
58 63   33     342 my $self = {
59             'bayes' => $bayes,
60 63         377 'supported_db_version' => 0,
61             'db_version' => undef,
62             };
63              
64             bless ($self, $class);
65              
66 63         172 $self;
67             }
68 63         196  
69             =item DB_VERSION
70              
71             public instance (Integer) DB_VERSION ()
72              
73             Description:
74             This method returns the currently supported database version for the
75             implementation.
76              
77             =cut
78              
79             my ($self) = @_;
80             return $self->{supported_db_version};
81             }
82 40     40 1 98  
83 40         313 =item read_db_configs
84              
85             public instance () read_db_configs ()
86              
87             Description:
88             This method reads any needed config variables from the configuration object
89             and then calls the Mail::SpamAssassin::Plugin::Bayes read_db_configs method.
90              
91             =cut
92              
93             my ($self) = @_;
94              
95             # TODO: at some stage, this may be useful to read config items which
96             # control database bloat, like
97 42     42 1 128 #
98             # - use of hapaxes
99             # - use of case-sensitivity
100             # - more midrange-hapax-avoidance tactics when parsing headers (future)
101             #
102             # for now, we just set these settings statically.
103             my $conf = $self->{bayes}->{main}->{conf};
104              
105             # Minimum desired database size? Expiry will not shrink the
106             # database below this number of entries. 100k entries is roughly
107 42         109 # equivalent to a 5Mb database file.
108             $self->{expiry_max_db_size} = $conf->{bayes_expiry_max_db_size};
109             $self->{expiry_pct} = $conf->{bayes_expiry_pct};
110             $self->{expiry_period} = $conf->{bayes_expiry_period};
111             $self->{expiry_max_exponent} = $conf->{bayes_expiry_max_exponent};
112 42         120  
113 42         88 $self->{bayes}->read_db_configs();
114 42         88 }
115 42         97  
116             =item prefork_init
117 42         195  
118             public instance (Boolean) prefork_init ()
119              
120             Description:
121             This optional method is called in the parent process shortly before
122             forking off child processes.
123              
124             =cut
125              
126             # sub prefork_init {
127             # my ($self) = @_;
128             # }
129              
130             =item spamd_child_init
131              
132             public instance (Boolean) spamd_child_init ()
133              
134             Description:
135             This optional method is called in a child process shortly after being spawned.
136              
137             =cut
138              
139             # sub spamd_child_init {
140             # my ($self) = @_;
141             # }
142              
143             =item tie_db_readonly
144              
145             public instance (Boolean) tie_db_readonly ()
146              
147             Description:
148             This method opens up the database in readonly mode.
149              
150             =cut
151              
152             my ($self) = @_;
153             die "bayes: tie_db_readonly: not implemented\n";
154             }
155              
156             =item tie_db_writable
157 0     0 1 0  
158 0         0 public instance (Boolean) tie_db_writable ()
159              
160             Description:
161             This method opens up the database in writable mode.
162              
163             Any callers of this methods should ensure that they call untie_db()
164             afterwards.
165              
166             =cut
167              
168             my ($self) = @_;
169             die "bayes: tie_db_writable: not implemented\n";
170             }
171              
172             =item untie_db
173              
174 0     0 1 0 public instance () untie_db ()
175 0         0  
176             Description:
177             This method unties the database.
178              
179             =cut
180              
181             my $self = shift;
182             die "bayes: untie_db: not implemented\n";
183             }
184              
185             =item calculate_expire_delta
186              
187             public instance (%) calculate_expire_delta (Integer $newest_atime,
188 0     0 1 0 Integer $start,
189 0         0 Integer $max_expire_mult)
190              
191             Description:
192             This method performs a calculation on the data to determine the optimum
193             atime for token expiration.
194              
195             =cut
196              
197             my ($self, $newest_atime, $start, $max_expire_mult) = @_;
198             die "bayes: calculate_expire_delta: not implemented\n";
199             }
200              
201             =item token_expiration
202              
203             public instance (Integer, Integer,
204             Integer, Integer) token_expiration(\% $opts,
205 0     0 1 0 Integer $newest_atime,
206 0         0 Integer $newdelta)
207              
208             Description:
209             This method performs the database specific expiration of tokens based on
210             the passed in C<$newest_atime> and C<$newdelta>.
211              
212             =cut
213              
214             my ($self, $opts, $newest_atime, $newdelta) = @_;
215             die "bayes: token_expiration: not implemented\n";
216             }
217              
218             =item expire_old_tokens
219              
220             public instance (Boolean) expire_old_tokens (\% hashref)
221              
222             Description:
223 0     0 1 0 This method expires old tokens from the database.
224 0         0  
225             =cut
226              
227             my ($self, $opts) = @_;
228             my $ret;
229              
230             my $eval_stat;
231             eval {
232             local $SIG{'__DIE__'}; # do not run user die() traps in here
233             if ($self->tie_db_writable()) {
234             $ret = $self->expire_old_tokens_trapped ($opts);
235             }
236             1;
237 0     0 1 0 } or do {
238 0         0 $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat;
239             };
240              
241             if (!$self->{bayes}->{main}->{learn_caller_will_untie}) {
242 0         0 $self->untie_db();
243 0 0       0 }
244 0         0  
245             if (defined $eval_stat) { # if we died, untie the dbs.
246 0         0 warn "bayes: expire_old_tokens: $eval_stat\n";
247 0 0       0 return 0;
248 0 0       0 }
  0         0  
249             $ret;
250             }
251 0 0       0  
252 0         0 =item expire_old_tokens_trapped
253              
254             public instance (Boolean) expire_old_tokens_trapped (\% $opts)
255 0 0       0  
256 0         0 Description:
257 0         0 This methods does the actual token expiration.
258              
259 0         0 XXX More docs here about the methodology and what not
260              
261             =cut
262              
263             my ($self, $opts) = @_;
264              
265             # Flag that we're doing work
266             $self->set_running_expire_tok();
267              
268             # We don't need to do an expire, so why were we called? Oh well.
269             if (!$self->expiry_due()) {
270             $self->remove_running_expire_tok();
271             return 0;
272             }
273              
274 0     0 1 0 my $started = time();
275             my @vars = $self->get_storage_variables();
276              
277 0         0 if ( $vars[10] > time ) {
278             dbg("bayes: expiry found newest atime in the future, resetting to current time");
279             $vars[10] = time;
280 0 0       0 }
281 0         0  
282 0         0 # How many tokens do we want to keep?
283             my $goal_reduction = int($self->{expiry_max_db_size} * $self->{expiry_pct});
284             dbg("bayes: expiry check keep size, ".$self->{expiry_pct}." * max: $goal_reduction");
285 0         0 # Make sure we keep at least 100000 tokens in the DB
286 0         0 if ( $goal_reduction < 100000 ) {
287             $goal_reduction = 100000;
288 0 0       0 dbg("bayes: expiry keep size too small, resetting to 100,000 tokens");
289 0         0 }
290 0         0 # Now turn goal_reduction into how many to expire.
291             $goal_reduction = $vars[3] - $goal_reduction;
292             dbg("bayes: token count: ".$vars[3].", final goal reduction size: $goal_reduction");
293              
294 0         0 if ( $goal_reduction < 1000 ) { # too few tokens to expire, abort.
295 0         0 dbg("bayes: reduction goal of $goal_reduction is under 1,000 tokens, skipping expire");
296             $self->set_last_expire(time());
297 0 0       0 $self->remove_running_expire_tok(); # this won't be cleaned up, so do it now.
298 0         0 return 1; # we want to indicate things ran as expected
299 0         0 }
300              
301             # Estimate new atime delta based on the last atime delta
302 0         0 my $newdelta = 0;
303 0         0 if ( $vars[9] > 0 ) {
304             # newdelta = olddelta * old / goal;
305 0 0       0 # this may seem backwards, but since we're talking delta here,
306 0         0 # not actual atime, we want smaller atimes to expire more tokens,
307 0         0 # and visa versa.
308 0         0 #
309 0         0 $newdelta = int($vars[8] * $vars[9] / $goal_reduction);
310             }
311              
312             # Calculate size difference between last expiration token removal
313 0         0 # count and the current goal removal count.
314 0 0       0 my $ratio = ($vars[9] == 0 || $vars[9] > $goal_reduction) ? $vars[9]/$goal_reduction : $goal_reduction/$vars[9];
315              
316             dbg("bayes: first pass? current: ".time().", Last: ".$vars[4].", atime: ".$vars[8].", count: ".$vars[9].", newdelta: $newdelta, ratio: $ratio, period: ".$self->{expiry_period});
317              
318             ## ESTIMATION PHASE
319             #
320 0         0 # Do this for the first expire or "odd" looking results cause a first pass to determine atime:
321             #
322             # - last expire was more than 30 days ago
323             # assume mail flow stays roughly the same month to month, recompute if it's > 1 month
324             # - last atime delta was under expiry period
325 0 0 0     0 # if we're expiring often max_db_size should go up, but let's recompute just to check
326             # - last reduction count was < 1000 tokens
327 0         0 # ditto
328             # - new estimated atime delta is under expiry period
329             # ditto
330             # - difference of last reduction to current goal reduction is > 50%
331             # if the two values are out of balance, estimating atime is going to be funky, recompute
332             #
333             if ( (time() - $vars[4] > 86400*30) || ($vars[8] < $self->{expiry_period}) || ($vars[9] < 1000)
334             || ($newdelta < $self->{expiry_period}) || ($ratio > 1.5) ) {
335             dbg("bayes: can't use estimation method for expiry, unexpected result, calculating optimal atime delta (first pass)");
336              
337             my $start = $self->{expiry_period}; # exponential search starting at ...? 1/2 day, 1, 2, 4, 8, 16, ...
338             my $max_expire_mult = 2**$self->{expiry_max_exponent}; # $max_expire_mult * $start = max expire time (256 days), power of 2.
339              
340             dbg("bayes: expiry max exponent: ".$self->{expiry_max_exponent});
341              
342             my %delta = $self->calculate_expire_delta($vars[10], $start, $max_expire_mult);
343              
344 0 0 0     0 return 0 unless (%delta);
      0        
      0        
      0        
345              
346 0         0 # This will skip the for loop if debugging isn't enabled ...
347             if (would_log('dbg', 'bayes')) {
348 0         0 dbg("bayes: atime\ttoken reduction");
349 0         0 dbg("bayes: ========\t===============");
350             for(my $i = 1; $i<=$max_expire_mult; $i <<= 1) {
351 0         0 dbg("bayes: ".$start*$i."\t".(exists $delta{$i} ? $delta{$i} : 0));
352             }
353 0         0 }
354            
355 0 0       0 # Now figure out which max_expire_mult value gives the closest results to goal_reduction, without
356             # going over ... Go from the largest delta backwards so the reduction size increases
357             # (tokens that expire at 4 also expire at 3, 2, and 1, so 1 will always be the largest expiry...)
358 0 0       0 #
359 0         0 for( ; $max_expire_mult > 0; $max_expire_mult>>=1 ) {
360 0         0 next unless exists $delta{$max_expire_mult};
361 0         0 if ($delta{$max_expire_mult} > $goal_reduction) {
362 0 0       0 $max_expire_mult<<=1; # the max expire is actually the next power of 2 out
363             last;
364             }
365             }
366              
367             # if max_expire_mult gets to 0, either we can't expire anything, or 1 is <= $goal_reduction
368             $max_expire_mult ||= 1;
369              
370 0         0 # $max_expire_mult is now equal to the value we should use ...
371 0 0       0 # Check to see if the atime value we found is really good.
372 0 0       0 # It's not good if:
373 0         0 # - $max_expire_mult would not expire any tokens. This means that the majority of
374 0         0 # tokens are old or new, and more activity is required before an expiry can occur.
375             # - reduction count < 1000, not enough tokens to be worth doing an expire.
376             #
377             if ( !exists $delta{$max_expire_mult} || $delta{$max_expire_mult} < 1000 ) {
378             dbg("bayes: couldn't find a good delta atime, need more token difference, skipping expire");
379 0   0     0 $self->set_last_expire(time());
380             $self->remove_running_expire_tok(); # this won't be cleaned up, so do it now.
381             return 1; # we want to indicate things ran as expected
382             }
383              
384             $newdelta = $start * $max_expire_mult;
385             dbg("bayes: first pass decided on $newdelta for atime delta");
386             }
387             else { # use the estimation method
388 0 0 0     0 dbg("bayes: can do estimation method for expiry, skipping first pass");
389 0         0 }
390 0         0  
391 0         0 my ($kept, $deleted, $num_hapaxes, $num_lowfreq) = $self->token_expiration($opts, $newdelta, @vars);
392 0         0  
393             my $done = time();
394              
395 0         0 my $msg = "expired old bayes database entries in ".($done - $started)." seconds";
396 0         0 my $msg2 = "$kept entries kept, $deleted deleted";
397              
398             if ($opts->{verbose}) {
399 0         0 my $hapax_pc = ($num_hapaxes * 100) / $kept;
400             my $lowfreq_pc = ($num_lowfreq * 100) / $kept;
401             print "$msg\n$msg2\n" or die "Error writing: $!";
402 0         0 printf "token frequency: 1-occurrence tokens: %3.2f%%\n", $hapax_pc
403             or die "Error writing: $!";
404 0         0 printf "token frequency: less than 8 occurrences: %3.2f%%\n", $lowfreq_pc
405             or die "Error writing: $!";
406 0         0 }
407 0         0 else {
408             dbg("bayes: $msg: $msg2");
409 0 0       0 }
410 0         0  
411 0         0 $self->remove_running_expire_tok();
412 0 0       0 return 1;
413 0 0       0 }
414              
415 0 0       0 =item sync_due
416              
417             public instance (Boolean) sync_due ()
418              
419 0         0 Description:
420             This methods determines if a sync is due.
421              
422 0         0 =cut
423 0         0  
424             my ($self) = @_;
425             die "bayes: sync_due: not implemented\n";
426             }
427              
428             =item expiry_due
429              
430             public instance (Boolean) expiry_due ()
431              
432             Description:
433             This methods determines if an expire is due.
434              
435             =cut
436 0     0 1 0  
437 0         0 my ($self) = @_;
438              
439             $self->read_db_configs(); # make sure this has happened here
440              
441             # If force expire was called, do the expire no matter what.
442             return 1 if ($self->{bayes}->{main}->{learn_force_expire});
443              
444             # if config says not to auto expire then no need to continue
445             return 0 if ($self->{bayes}->{main}->{conf}->{bayes_auto_expire} == 0);
446              
447             # is the database too small for expiry? (Do *not* use "scalar keys",
448             # as this will iterate through the entire db counting them!)
449             my @vars = $self->get_storage_variables();
450 4     4 1 16 my $ntoks = $vars[3];
451              
452 4         35 my $last_expire = time() - $vars[4];
453             if (!$self->{bayes}->{main}->{ignore_safety_expire_timeout}) {
454             # if we're not ignoring the safety timeout, don't run an expire more
455 4 50       17 # than once every 12 hours.
456             return 0 if ($last_expire < 43200);
457             }
458 4 50       27 else {
459             # if we are ignoring the safety timeout (e.g.: mass-check), still
460             # limit the expiry to only one every 5 minutes.
461             return 0 if ($last_expire < 300);
462 4         19 }
463 4         10  
464             dbg("bayes: DB expiry: tokens in DB: $ntoks, Expiry max size: ".$self->{expiry_max_db_size}.", Oldest atime: ".$vars[5].", Newest atime: ".$vars[10].", Last expire: ".$vars[4].", Current time: ".time());
465 4         14  
466 4 50       17 my $conf = $self->{bayes}->{main}->{conf};
467             if ($ntoks <= 100000 || # keep at least 100k tokens
468             $self->{expiry_max_db_size} > $ntoks || # not enough tokens to cause an expire
469 4 50       12 $vars[10]-$vars[5] < 43200 || # delta between oldest and newest < 12h
470             $self->{db_version} < $self->DB_VERSION # ignore old db formats
471             ) {
472             return 0;
473             }
474 0 0       0  
475             return 1;
476             }
477 4         36  
478             =item seen_get
479 4         14  
480 4 0 33     19 public instance (Char) seen_get (String $msgid)
      33        
      0        
481              
482             Description:
483             This method retrieves the stored value, if any, for C<$msgid>. The return
484             value is the stored string ('s' for spam and 'h' for ham) or undef if
485 4         36 C<$msgid> is not found.
486              
487             =cut
488 0            
489             my ($self, $msgid) = @_;
490             die "bayes: seen_get: not implemented\n";
491             }
492              
493             =item seen_put
494              
495             public instance (Boolean) seen_put (String $msgid, Char $flag)
496              
497             Description:
498             This method records C<$msgid> as the type given by C<$flag>. C<$flag> is
499             one of two values 's' for spam and 'h' for ham.
500              
501             =cut
502              
503 0     0 1   my ($self, $msgid, $flag) = @_;
504 0           die "bayes: seen_put: not implemented\n";
505             }
506              
507             =item seen_delete
508              
509             public instance (Boolean) seen_delete (String $msgid)
510              
511             Description:
512             This method removes C<$msgid> from storage.
513              
514             =cut
515              
516             my ($self, $msgid) = @_;
517             die "bayes: seen_delete: not implemented\n";
518 0     0 1   }
519 0            
520             =item get_storage_variables
521              
522             public instance (@) get_storage_variables ()
523              
524             Description:
525             This method retrieves the various administrative variables used by
526             the Bayes storage implementation.
527              
528             The values returned in the array are in the following order:
529              
530             0: scan count base
531              
532 0     0 1   1: number of spam
533 0            
534             2: number of ham
535              
536             3: number of tokens in db
537              
538             4: last expire atime
539              
540             5: oldest token in db atime
541              
542             6: db version value
543              
544             7: last journal sync
545              
546             8: last atime delta
547              
548             9: last expire reduction count
549              
550             10: newest token in db atime
551              
552             =cut
553              
554             my ($self) = @_;
555             die "bayes: get_storage_variables: not implemented\n";
556             }
557              
558             =item dump_db_toks
559              
560             public instance () dump_db_toks (String $template, String $regex, @ @vars)
561              
562             Description:
563             This method loops over all tokens, computing the probability for the token
564             and then printing it out according to the passed in template.
565              
566             =cut
567              
568             my ($self, $template, $regex, @vars) = @_;
569             die "bayes: dump_db_toks: not implemented\n";
570             }
571 0     0 1    
572 0           =item set_last_expire
573              
574             public instance (Boolean) _set_last_expire (Integer $time)
575              
576             Description:
577             This method sets the last expire time.
578              
579             =cut
580              
581             my ($self, $time) = @_;
582             die "bayes: set_last_expire: not implemented\n";
583             }
584              
585             =item get_running_expire_tok
586 0     0 1    
587 0           public instance (Time) get_running_expire_tok ()
588              
589             Description:
590             This method determines if an expire is currently running and returns the time
591             the expire started.
592              
593             =cut
594              
595             my ($self) = @_;
596             die "bayes: get_running_expire_tok: not implemented\n";
597             }
598              
599             =item set_running_expire_tok
600 0     0 1    
601 0           public instance (Time) set_running_expire_tok ()
602              
603             Description:
604             This method sets the running expire time to the current time.
605              
606             =cut
607              
608             my ($self) = @_;
609             die "bayes: set_running_expire_tok: not implemented\n";
610             }
611              
612             =item remove_running_expire_tok
613              
614             public instance (Boolean) remove_running_expire_tok ()
615 0     0 1    
616 0           Description:
617             This method removes a currently set running expire time.
618              
619             =cut
620              
621             my ($self) = @_;
622             die "bayes: remove_running_expire_tok: not implemented\n";
623             }
624              
625             =item tok_get
626              
627             public instance (Integer, Integer, Time) tok_get (String $token)
628              
629 0     0 1   Description:
630 0           This method retrieves the specified token (C<$token>) from storage and returns
631             it's spam count, ham count and last access time.
632              
633             =cut
634              
635             my ($self, $token) = @_;
636             die "bayes: tok_get: not implemented\n";
637             }
638              
639             =item tok_get_all
640              
641             public instance (\@) tok_get_all (@ @tokens)
642              
643 0     0 1   Description:
644 0           This method retrieves the specified tokens (C<@tokens>) from storage and
645             returns an array ref of arrays spam count, ham count and last access time.
646              
647             =cut
648              
649             my ($self, $tokens) = @_;
650             die "bayes: tok_get_all: not implemented\n";
651             }
652              
653             =item tok_count_change
654              
655             public instance (Boolean) tok_count_change (Integer $spam_count,
656             Integer $ham_count,
657             String $token,
658 0     0 1   Time $atime)
659 0            
660             Description:
661             This method takes a C<$spam_count> and C<$ham_count> and adds it to
662             C<$token> along with updating C<$token>s atime with C<$atime>.
663              
664             =cut
665              
666             my ($self, $spam_count, $ham_count, $token, $atime) = @_;
667             die "bayes: tok_count_change: not implemented\n";
668             }
669              
670             =item multi_tok_count_change
671              
672             public instance (Boolean) multi_tok_count_change (Integer $spam_count,
673 0     0 1   Integer $ham_count,
674 0           \% $tokens,
675             String $atime)
676              
677             Description:
678             This method takes a C<$spam_count> and C<$ham_count> and adds it to all
679             of the tokens in the C<$tokens> hash ref along with updating each tokens
680             atime with C<$atime>.
681              
682             =cut
683              
684             my ($self, $spam_count, $ham_count, $tokens, $atime) = @_;
685             die "bayes: multi_tok_count_change: not implemented\n";
686             }
687              
688             =item nspam_nham_get
689              
690             public instance (Integer, Integer) nspam_nham_get ()
691 0     0 1    
692 0           Description:
693             This method retrieves the total number of spam and the total number of ham
694             currently under storage.
695              
696             =cut
697              
698             my ($self) = @_;
699             die "bayes: nspam_nham_get: not implemented\n";
700             }
701              
702             =item nspam_nham_change
703              
704             public instance (Boolean) nspam_nham_change (Integer $num_spam,
705             Integer $num_ham)
706              
707             Description:
708             This method updates the number of spam and the number of ham in the database.
709              
710 0     0 1   =cut
711 0            
712             my ($self, $num_spam, $num_ham) = @_;
713             die "bayes: nspam_nham_change: not implemented\n";
714             }
715              
716             =item tok_touch
717              
718             public instance (Boolean) tok_touch (String $token,
719             Time $atime)
720              
721             Description:
722             This method updates the given tokens (C<$token>) access time.
723              
724             =cut
725 0     0 1    
726 0           my ($self, $token, $atime) = @_;
727             die "bayes: tok_touch: not implemented\n";
728             }
729              
730             =item tok_touch_all
731              
732             public instance (Boolean) tok_touch_all (\@ $tokens,
733             Time $atime)
734              
735             Description:
736             This method does a mass update of the given list of tokens C<$tokens>, if the existing token
737             atime is < C<$atime>.
738              
739             =cut
740 0     0 1    
741 0           my ($self, $tokens, $atime) = @_;
742             die "bayes: tok_touch_all: not implemented\n";
743             }
744              
745             =item cleanup
746              
747             public instance (Boolean) cleanup ()
748              
749             Description:
750             This method performs any cleanup necessary before moving onto the next
751             operation.
752              
753             =cut
754              
755 0     0 1   my ($self) = @_;
756 0           die "bayes: cleanup: not implemented\n";
757             }
758              
759             =item get_magic_re
760              
761             public instance get_magic_re (String)
762              
763             Description:
764             This method returns a regexp which indicates a magic token.
765              
766             =cut
767              
768             my ($self) = @_;
769             die "bayes: get_magic_re: not implemented\n";
770             }
771 0     0 1    
772 0           =item sync
773              
774             public instance (Boolean) sync (\% $opts)
775              
776             Description:
777             This method performs a sync of the database.
778              
779             =cut
780              
781             my ($self, $opts) = @_;
782             die "bayes: sync: not implemented\n";
783             }
784              
785             =item perform_upgrade
786 0     0 1    
787 0           public instance (Boolean) perform_upgrade (\% $opts)
788              
789             Description:
790             This method is a utility method that performs any necessary upgrades
791             between versions. It should know how to handle previous versions and
792             what needs to happen to upgrade them.
793              
794             A true return value indicates success.
795              
796             =cut
797              
798             my ($self, $opts) = @_;
799             die "bayes: perform_upgrade: not implemented\n";
800 0     0 1   }
801 0            
802             =item clear_database
803              
804             public instance (Boolean) clear_database ()
805              
806             Description:
807             This method deletes all records for a particular user.
808              
809             Callers should be aware that any errors returned by this method
810             could causes the database to be inconsistent for the given user.
811              
812             =cut
813              
814 0     0 1   my ($self) = @_;
815 0           die "bayes: clear_database: not implemented\n";
816             }
817              
818             =item backup_database
819              
820             public instance (Boolean) backup_database ()
821              
822             Description:
823             This method will dump the users database in a machine readable format.
824              
825             =cut
826              
827             my ($self) = @_;
828             die "bayes: backup_database: not implemented\n";
829             }
830              
831             =item restore_database
832 0     0 1    
833 0           public instance (Boolean) restore_database (String $filename, Boolean $showdots)
834              
835             Description:
836             This method restores a database from the given filename, C<$filename>.
837              
838             Callers should be aware that any errors returned by this method
839             could causes the database to be inconsistent for the given user.
840              
841             =cut
842              
843             my ($self, $filename, $showdots) = @_;
844             die "bayes: restore_database: not implemented\n";
845             }
846              
847             =item db_readable
848              
849 0     0 1   public instance (Boolean) db_readable ()
850 0            
851             Description:
852             This method returns whether or not the Bayes DB is available in a
853             readable state.
854              
855             =cut
856              
857             my ($self) = @_;
858             die "bayes: db_readable: not implemented\n";
859             }
860              
861             =item db_writable
862              
863 0     0 1   public instance (Boolean) db_writable ()
864 0            
865             Description:
866             This method returns whether or not the Bayes DB is available in a
867             writable state.
868              
869             =cut
870              
871             my ($self) = @_;
872             die "bayes: db_writable: not implemented\n";
873             }
874              
875              
876              
877             1;
878              
879             =back
880 0     0 1    
881 0           =cut