File Coverage

blib/lib/DBR/Config/Scope.pm
Criterion Covered Total %
statement 75 84 89.2
branch 21 34 61.7
condition 7 9 77.7
subroutine 7 8 87.5
pod 0 4 0.0
total 110 139 79.1


line stmt bran cond sub pod time code
1             # the contents of this file are Copyright (c) 2009 Daniel Norman
2             # This program is free software; you can redistribute it and/or
3             # modify it under the terms of the GNU General Public License as
4             # published by the Free Software Foundation.
5              
6             package DBR::Config::Scope;
7              
8 18     18   97 use strict;
  18         41  
  18         609  
9 18     18   271 use base 'DBR::Common';
  18         40  
  18         1616  
10 18     18   101 use Digest::MD5 qw(md5_base64);
  18         42  
  18         27270  
11              
12             my %SCOPE_CACHE;
13             my %FIELD_CACHE;
14              
15             sub new {
16 37     37 0 98 my( $package ) = shift;
17 37         201 my %params = @_;
18 37         206 my $self = {
19             session => $params{session},
20             instance => $params{conf_instance},
21             extra_ident => $params{extra_ident},
22             };
23              
24 37         125 bless( $self, $package );
25              
26 37 50       255 return $self->_error('session is required') unless $self->{session};
27 37 50       145 return $self->_error('conf_instance is required') unless $self->{instance};
28              
29 37   100     238 my $offset = $params{offset} || 1;
30 37 50       300 my $scope_id = $self->_get_scope_id($offset + 1) or return $self->_error('failed to determine scope_id');
31              
32 37         166 $self->{scope_id} = $scope_id;
33              
34 37         938 return $self;
35             }
36              
37              
38             sub purge_all{
39 0     0 0 0 %SCOPE_CACHE = ();
40 0         0 %FIELD_CACHE = ();
41              
42 0         0 return 1;
43             }
44              
45             sub _get_scope_id{
46 37     37   82 my $self = shift;
47 37         78 my $offset = shift;
48              
49 37         81 my @parts;
50 37         150 while($offset < 100){
51 37         326 my (undef,$file,$line,$method) = caller($offset++);
52 37 50       257 if($file =~ /^\//){ # starts with Slash
53 0         0 $offset = 101; #everything is good
54             }else{
55 37 50       165 if ($file !~ /^\(eval/){ # If it's an eval, then we do another loop
56             # Not an eval, just slap on the directory we are in and call it done
57 37         184 $file = $ENV{'PWD'} . '/' . $file;
58 37         87 $offset = 101;
59             }
60             }
61              
62 37         205 push @parts, $file . '*' . $line;
63             }
64              
65 37         129 my $ident = join('|',grep {$_} (@parts,$self->{extra_ident}));
  74         570  
66              
67 37         393 $self->_logDebug3("SCOPE: '$ident'");
68              
69 37         344 my $digest = md5_base64($ident);
70              
71 37         308 my $scope_id = $SCOPE_CACHE{$digest}; # Check the cache!
72 37 100       144 if($scope_id){
73 11         118 $self->_logDebug2('Found cached scope');
74 11         96 return $scope_id;
75             }
76              
77 26         71 my $instance = $self->{instance};
78 26 50       1318 my $dbrh = $instance->connect or return $self->_error("Failed to connect to ${\$instance->name}");
  0         0  
79              
80             # If the insert fails, that means someone else has won the race condition, try try again
81 26         58 my $try;
82 26         109 while(++$try < 3){
83             #Yeahhh... using the old way for now, Don't you like absurd recursion? perhaps change this?
84 26         265 my $record = $dbrh->select(
85             -table => 'cache_scopes',
86             -fields => 'scope_id',
87             -where => {digest => $digest},
88             -single => 1,
89             );
90              
91 26 50       1296 return $SCOPE_CACHE{$digest} = $record->{scope_id} if $record;
92              
93 26         426 my $scope_id = $dbrh->insert(
94             -table => 'cache_scopes',
95             -fields => {
96             digest => $digest
97             },
98             -quiet => 1,
99             );
100              
101 26 50       502 return $SCOPE_CACHE{$digest} = $scope_id if $scope_id;
102             }
103              
104 0         0 return $self->_error('Something failed');
105             }
106              
107             sub fields{
108 37     37 0 87 my $self = shift;
109 37   100     387 my $cache = $FIELD_CACHE{ $self->{scope_id} } ||= [undef,[]];
110              
111 37         72 my $fids;
112 37 100 66     334 if ($cache->[0] && ($cache->[0] + 300 > time)){
113 11         31 $fids = $cache->[1];
114             }
115              
116 37 100       373 if(!$fids){
117              
118 26         76 my $instance = $self->{instance};
119 26 50       207 my $dbrh = $instance->connect or return $self->_error("Failed to connect to ${\$instance->name}");
  0         0  
120              
121 26 50       337 my $fields = $dbrh->select(
122             -table => 'cache_fielduse',
123             -fields => 'field_id',
124             -where => { scope_id => ['d',$self->{scope_id}] },
125             ) or return $self->_error('Failed to select from cache_fielduse');
126 26         158 $fids = [map { $_->{field_id} } @$fields];
  0         0  
127 26         89 $cache->[0] = time;
128 26         180 $cache->[1] = $fids;
129             }
130              
131 37         93 my @fields;
132 37         152 foreach my $fid (@$fids){
133 12 50       65 my $field = DBR::Config::Field->new(
134             session => $self->{session},
135             field_id => $fid,
136             ) or return $self->_error('failed to create table object');
137 12         48 push @fields, $field;
138             }
139              
140              
141 37         251 return \@fields;
142             }
143              
144             sub addfield{
145 42     42 0 88 my $self = shift;
146 42         91 my $field = shift;
147              
148 42         454 my $fid = $field->field_id;
149              
150 42 100       406 return 1 if $self->{fcache}->{ $fid }++; # quick cache
151              
152 16   50     106 my $cache = $FIELD_CACHE{ $self->{scope_id} } ||= [undef,[]];
153              
154 16 50       160 return 1 if $self->_b_in($fid,$cache->[1]); # already have it
155              
156 16         142 $cache->[0] = time;
157 16         32 push @{$cache->[1]}, $fid;
  16         58  
158              
159 16         41 my $instance = $self->{instance};
160 16 50       98 my $dbrh = $instance->connect or return $self->_error("Failed to connect to ${\$instance->name}");
  0         0  
161              
162             # Don't check for failure, the unique index constraint will reject the insert in case of a race condition
163 16         253 my $row_id = $dbrh->insert(
164             -table => 'cache_fielduse',
165             -fields => {
166             scope_id => ['d',$self->{scope_id}],
167             field_id => ['d',$fid]
168             },
169             -quiet => 1,
170             );
171              
172             # $dbrh->minsert('cache_fielduse',
173             # scope_id => $self->{scope_id},
174             # field_id => $fid
175             # );
176              
177 16         200 return 1;
178             }
179              
180             1;