line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package CGI::Application::Plugin::DBIProfile::Driver; |
2
|
1
|
|
|
1
|
|
6
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
41
|
|
3
|
1
|
|
|
1
|
|
945
|
use IO::Scalar; |
|
1
|
|
|
|
|
18921
|
|
|
1
|
|
|
|
|
66
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 TODO: POD |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=cut |
8
|
|
|
|
|
|
|
|
9
|
1
|
|
|
1
|
|
12
|
use vars qw($VERSION $DEBUG @ISA); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
123
|
|
10
|
|
|
|
|
|
|
$DEBUG = 0; |
11
|
|
|
|
|
|
|
$VERSION = "1.1"; |
12
|
|
|
|
|
|
|
@ISA = qw(DBI::ProfileDumper); |
13
|
|
|
|
|
|
|
# TODO: requires DBI 1.49 for class method call interface. |
14
|
|
|
|
|
|
|
# TODO: requires DBI 1.24 for DBI->{Profile} support, period. |
15
|
1
|
|
|
1
|
|
7
|
use Carp qw(carp croak); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
69
|
|
16
|
1
|
|
|
1
|
|
8385
|
use DBI; |
|
1
|
|
|
|
|
37558
|
|
|
1
|
|
|
|
|
86
|
|
17
|
1
|
|
|
1
|
|
1090
|
use DBI::ProfileDumper; |
|
1
|
|
|
|
|
8895
|
|
|
1
|
|
|
|
|
705
|
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# Override flush_to_disk() to use IO::Scalar rather than a real file. |
20
|
|
|
|
|
|
|
# Also, change it to return the current formatted dataset, rather |
21
|
|
|
|
|
|
|
# than write anything out. |
22
|
|
|
|
|
|
|
# NOTE: the name doesn't fit. Could change that. |
23
|
|
|
|
|
|
|
sub flush_to_disk |
24
|
|
|
|
|
|
|
{ |
25
|
0
|
|
|
0
|
1
|
|
my $self = _get_dbiprofile_obj(shift); |
26
|
0
|
0
|
|
|
|
|
return unless defined $self; |
27
|
|
|
|
|
|
|
|
28
|
0
|
|
|
|
|
|
my $output = $self->get_current_stats(); |
29
|
|
|
|
|
|
|
|
30
|
0
|
|
|
|
|
|
$self->empty(); |
31
|
|
|
|
|
|
|
|
32
|
0
|
|
|
|
|
|
return $output; |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# This does what flush_to_disk does, without emptying data afterwards. |
36
|
|
|
|
|
|
|
sub get_current_stats |
37
|
|
|
|
|
|
|
{ |
38
|
0
|
|
|
0
|
0
|
|
my $self = _get_dbiprofile_obj(shift); |
39
|
0
|
0
|
|
|
|
|
return unless defined $self; |
40
|
|
|
|
|
|
|
|
41
|
0
|
|
|
|
|
|
my $data = $self->{Data}; |
42
|
|
|
|
|
|
|
|
43
|
0
|
|
|
|
|
|
my $output; |
44
|
0
|
|
|
|
|
|
my $fh = new IO::Scalar \$output; |
45
|
|
|
|
|
|
|
|
46
|
0
|
|
|
|
|
|
$self->write_header($fh); |
47
|
0
|
|
|
|
|
|
$self->write_data($fh, $self->{Data}, 1); |
48
|
|
|
|
|
|
|
|
49
|
0
|
0
|
|
|
|
|
close($fh) or croak("Unable to close scalar filehandle: $!"); |
50
|
|
|
|
|
|
|
|
51
|
0
|
|
|
|
|
|
return $output; |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# Override on_destroy() to simply clear the data, and close the IO::Scalar. |
55
|
|
|
|
|
|
|
sub on_destroy |
56
|
|
|
|
|
|
|
{ |
57
|
0
|
|
|
0
|
0
|
|
shift->empty(); |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# Override empty to it'll behave has a class method. |
61
|
|
|
|
|
|
|
sub empty |
62
|
|
|
|
|
|
|
{ |
63
|
0
|
|
|
0
|
1
|
|
my $self = _get_dbiprofile_obj(shift); |
64
|
0
|
0
|
|
|
|
|
return unless defined $self; |
65
|
0
|
|
|
|
|
|
$self->SUPER::empty; |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
# utility method to get a usable DBI::Profile object. |
69
|
|
|
|
|
|
|
sub _get_dbiprofile_obj |
70
|
|
|
|
|
|
|
{ |
71
|
0
|
|
|
0
|
|
|
my $self = shift; |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
# if we're called by an instance var, just return it. |
74
|
0
|
0
|
0
|
|
|
|
return $self if ref $self and UNIVERSAL::isa($self, 'DBI::Profile'); |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
# XXX: I couldn't find an instance where I needed to look at more |
77
|
|
|
|
|
|
|
# than one database handle, even with multiple database handles |
78
|
|
|
|
|
|
|
# talking to separate dbs using separate drivers. |
79
|
|
|
|
|
|
|
# I'm not sure how this works out under mod_perl2 using the |
80
|
|
|
|
|
|
|
# multi-threaded apache service (is there a separate perl memory/name |
81
|
|
|
|
|
|
|
# space for each thread, or one per process?) |
82
|
|
|
|
|
|
|
# We may need to loop over handles, fetch data && clear data && merge. |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
# if we're called as a class method, we need to find at least one |
85
|
|
|
|
|
|
|
# db handle to work with, and snag its profile. |
86
|
0
|
|
|
|
|
|
my $dbh = (_get_all_dbh_handles())[0]; |
87
|
0
|
0
|
0
|
|
|
|
unless (ref $dbh && UNIVERSAL::isa($dbh, 'DBI::db')) |
88
|
|
|
|
|
|
|
{ |
89
|
0
|
0
|
|
|
|
|
carp "Unable to locate active dbh." if $DEBUG; |
90
|
0
|
|
|
|
|
|
return; |
91
|
|
|
|
|
|
|
} |
92
|
0
|
|
|
|
|
|
$self = $dbh->{Profile}; |
93
|
0
|
0
|
|
|
|
|
if (! ref $self) { |
94
|
0
|
|
|
|
|
|
carp "Handle lacks Profile support"; |
95
|
0
|
|
|
|
|
|
return; |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
0
|
|
|
|
|
|
return $self; |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# utility methods to enumerate all database handles |
102
|
|
|
|
|
|
|
sub _get_all_dbh_handles |
103
|
|
|
|
|
|
|
{ |
104
|
0
|
|
|
0
|
|
|
return grep { $_->{Type} eq 'db' } _get_all_dbi_handles(); |
|
0
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
sub _get_all_dbi_handles |
107
|
|
|
|
|
|
|
{ |
108
|
0
|
|
|
0
|
|
|
my @handles; |
109
|
0
|
|
|
|
|
|
my %drivers = DBI->installed_drivers(); |
110
|
0
|
|
|
|
|
|
push(@handles, _get_all_dbi_child_handles($_) ) for values %drivers; |
111
|
0
|
|
|
|
|
|
return @handles; |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
sub _get_all_dbi_child_handles |
114
|
|
|
|
|
|
|
{ |
115
|
0
|
|
|
0
|
|
|
my $h = shift; |
116
|
0
|
|
|
|
|
|
my @h = ($h); |
117
|
0
|
|
|
|
|
|
push(@h, _get_all_dbi_child_handles($_)) |
118
|
0
|
|
|
|
|
|
for (grep { defined } @{$h->{ChildHandles}}); |
|
0
|
|
|
|
|
|
|
119
|
0
|
|
|
|
|
|
return @h; |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
1; |