| 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; |