File Coverage

blib/lib/Logfile/EPrints/Filter/Session.pm
Criterion Covered Total %
statement 75 75 100.0
branch 22 28 78.5
condition 13 20 65.0
subroutine 18 18 100.0
pod 0 1 0.0
total 128 142 90.1


line stmt bran cond sub pod time code
1             package Logfile::EPrints::Filter::Session;
2              
3 6     6   36 use strict;
  6         11  
  6         252  
4              
5 6     6   32 use vars qw( %SESSIONS $AUTOLOAD $TIDY_ON $TIDY_COUNT );
  6         13  
  6         2965  
6              
7             $TIDY_ON = 10000;
8             $TIDY_COUNT = 0;
9              
10             sub new
11             {
12 3     3 0 34 my ($class,%self) = @_;
13 3   50     23 $self{session} ||= 'Logfile::EPrints::Session';
14 3         5 $TIDY_COUNT = 0;
15 3   33     39 bless \%self, ref($class) || $class;
16             }
17              
18             sub AUTOLOAD
19             {
20 24 50   24   89 return if $AUTOLOAD =~ /[A-Z]$/;
21 24         99 $AUTOLOAD =~ s/^.*:://;
22 24         43 my( $self, $hit ) = @_;
23 24         82 my $address = $hit->address;
24 24 100 100     98 if( exists $SESSIONS{$address} and
25             $SESSIONS{$address}->expired_by( $hit ) )
26             {
27 1         201 delete($SESSIONS{$address})->end_session;
28             }
29 24   66     1641 my $session = $SESSIONS{$address} ||=
30             $self->{session}->new(
31             filter => $self,
32             address => $address,
33             );
34 24         108 $session->$AUTOLOAD( $hit );
35            
36 24 100       64 $self->_tidyup( $hit ) if ++$TIDY_COUNT > $TIDY_ON;
37            
38 24         54 $hit->{session} = $session;
39 24         115 return $self->{handler}->$AUTOLOAD($hit);
40             }
41              
42             sub _tidyup
43             {
44 1     1   3 my( $self, $hit ) = @_;
45 1         3 $TIDY_COUNT = 0;
46 1         6 for(keys %SESSIONS)
47             {
48 2 100       11 if( $SESSIONS{$_}->expired_by( $hit ) )
49             {
50 1         5 delete($SESSIONS{$_})->end_session;
51             };
52             }
53             }
54              
55             package Logfile::EPrints::Session;
56              
57             =head1 NAME
58              
59             Logfile::EPrints::Session - Simple session class
60              
61             =head1 METHODS
62              
63             =over 4
64              
65             =cut
66              
67 6     6   38 use strict;
  6         10  
  6         221  
68 6     6   37 use warnings;
  6         32  
  6         246  
69              
70 6     6   29 use vars qw( $AUTOLOAD $MAX_SESSION_GAP );
  6         11  
  6         3194  
71              
72             $MAX_SESSION_GAP = 60*10; # 10 minutes
73              
74             sub new
75             {
76 6     6   44 my( $class, %self ) = @_;
77 6         39 bless \%self, $class;
78             }
79              
80             =item $session->expired_by( $hit )
81              
82             Returns true if this session would be expired before $hit occurred. NOTE for the purposes of tidyup $hit may not be from the same address as the session.
83              
84             =cut
85              
86 21     21   61 sub expired_by { ($_[1]->utime - $_[0]->{last_seen}) > $MAX_SESSION_GAP }
87              
88             =item $session->start_session( $hit )
89              
90             A new session has started with $hit.
91              
92             =cut
93              
94 6     6   8 sub start_session {}
95              
96             =item $session->end_session
97              
98             The session has expired/finished.
99              
100             =cut
101              
102 2     2   8 sub end_session { delete $_[0]->{last_abstract} }
103              
104             =item $session->total( [ $type ] )
105              
106             Return the total number of requests in this session or, if $type is given, total unique requests (by identifier) for $type.
107              
108             =cut
109              
110             sub total
111             {
112 11     11   14 my( $self, $type ) = @_;
113              
114 11         52 return @_ == 2 ?
115 11 50       23 scalar keys %{$self->{requests}->{$type}} :
116             $self->{requests}->{total};
117             }
118              
119             sub AUTOLOAD
120             {
121 24 50   24   75 return if $AUTOLOAD =~ /[A-Z]$/;
122 24         89 $AUTOLOAD =~ s/^.*:://;
123 24         42 my( $self, $hit ) = @_;
124              
125 24 100       56 if( !defined $self->{last_seen} )
126             {
127 6         23 $self->{first_seen} = $hit->utime;
128 6         906 $self->start_session( $hit );
129             }
130              
131 24 100 66     141 if( $AUTOLOAD eq 'abstract' )
    100          
132             {
133 1         33 $self->{last_abstract} = $hit; # creates a loop in this hit
134             }
135             elsif( $AUTOLOAD eq 'fulltext' and exists $self->{last_abstract} )
136             {
137 3 100       23 if( $self->{last_abstract}->identifier eq $hit->identifier )
138             {
139 2         12 $hit->{abstract_referrer} = $self->{last_abstract};
140             }
141             else
142             {
143 1         14 delete $self->{last_abstract};
144             }
145             }
146            
147 24         198 $self->{last_seen} = $hit->utime;
148            
149 24 50 66     104 if( $AUTOLOAD eq 'abstract' or $AUTOLOAD eq 'fulltext' )
150             {
151 24         50 $self->{requests}->{total}++;
152 24         130 $self->{requests}->{$AUTOLOAD}->{$hit->identifier}++;
153             }
154             }
155              
156             package Logfile::EPrints::Filter::MaxPerSession;
157              
158 6     6   37 use strict;
  6         17  
  6         199  
159 6     6   31 use warnings;
  6         10  
  6         344  
160              
161             our @ISA = qw( Logfile::EPrints::Filter );
162              
163 6     6   27 use vars qw( $AUTOLOAD );
  6         12  
  6         2031  
164              
165             sub AUTOLOAD
166             {
167 11 50   11   33 return if $AUTOLOAD =~ /[A-Z]$/;
168 11         31 $AUTOLOAD =~ s/^.*:://;
169 11         15 my( $self, $hit ) = @_;
170 11 100 66     47 if( defined($self->{$AUTOLOAD}) and
171             $hit->{session}->total($AUTOLOAD) > $self->{$AUTOLOAD} )
172             {
173 1 50       6 return undef if $hit->{session}->{__PACKAGE__ . '_removed'};
174 1         4 $hit->{session}->{__PACKAGE__ . '_removed'} = 1;
175 1         5 return Logfile::EPrints::Hit::Negate->new(
176             address => $hit->address,
177             start_utime => $hit->{session}->{first_seen},
178             end_utime => $hit->{session}->{last_seen},
179             );
180             }
181             else
182             {
183 10         29 return $self->{handler}->$AUTOLOAD( $hit );
184             }
185             }
186              
187             1;
188              
189             __END__