line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Pgtools::Kill; |
2
|
1
|
|
|
1
|
|
35288
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
21
|
|
3
|
1
|
|
|
1
|
|
3
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
16
|
|
4
|
1
|
|
|
1
|
|
758
|
use DateTime; |
|
1
|
|
|
|
|
69883
|
|
|
1
|
|
|
|
|
32
|
|
5
|
1
|
|
|
1
|
|
489
|
use DateTime::Format::Strptime; |
|
1
|
|
|
|
|
19081
|
|
|
1
|
|
|
|
|
4
|
|
6
|
1
|
|
|
1
|
|
85
|
use DBI; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
28
|
|
7
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
294
|
use Pgtools; |
|
1
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
21
|
|
9
|
1
|
|
|
1
|
|
305
|
use Pgtools::Connection; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
use Pgtools::Query; |
11
|
|
|
|
|
|
|
use parent qw(Class::Accessor); |
12
|
|
|
|
|
|
|
__PACKAGE__->mk_accessors(qw(help ignore_match_query ignore_match_state kill match_query match_state print run_time version)); |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
our ($now, $qt) ; |
15
|
|
|
|
|
|
|
our $qt_format = DateTime::Format::Strptime->new( |
16
|
|
|
|
|
|
|
pattern => '%Y-%m-%d %H:%M:%S.%N' |
17
|
|
|
|
|
|
|
); |
18
|
|
|
|
|
|
|
our $start_time = DateTime->now( time_zone => 'Asia/Tokyo' ); |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
sub exec { |
21
|
|
|
|
|
|
|
my ($self, $arg) = @_; |
22
|
|
|
|
|
|
|
my $default = { |
23
|
|
|
|
|
|
|
"host" => "localhost", |
24
|
|
|
|
|
|
|
"port" => "5432", |
25
|
|
|
|
|
|
|
"user" => "postgres", |
26
|
|
|
|
|
|
|
"password" => "", |
27
|
|
|
|
|
|
|
"database" => "postgres" |
28
|
|
|
|
|
|
|
}; |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
my $db = Pgtools::Connection->new($default); |
31
|
|
|
|
|
|
|
$db->set_args($arg); |
32
|
|
|
|
|
|
|
$db->create_connection(); |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# return hash reference |
35
|
|
|
|
|
|
|
my $queries = &search_queries($self, $db); |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
if($self->print and !$self->kill) { |
38
|
|
|
|
|
|
|
&print_query($queries); |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
if($self->kill){ |
41
|
|
|
|
|
|
|
&kill_queries($db, $self, $queries); |
42
|
|
|
|
|
|
|
print "Killed matched queries!\n"; |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
$db->dbh->disconnect; |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
sub kill_queries { |
49
|
|
|
|
|
|
|
my ($db, $self, $queries) = @_; |
50
|
|
|
|
|
|
|
my ($sth, $now); |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
foreach my $pid (keys(%$queries)) { |
53
|
|
|
|
|
|
|
$sth = $db->dbh->prepare("SELECT pg_terminate_backend(".$pid.");"); |
54
|
|
|
|
|
|
|
$now = DateTime->now( time_zone => 'local' ); |
55
|
|
|
|
|
|
|
$sth->execute(); |
56
|
|
|
|
|
|
|
if($self->print) { |
57
|
|
|
|
|
|
|
print "-------------------------------\n"; |
58
|
|
|
|
|
|
|
print "Killed-pid: ".$pid."\n"; |
59
|
|
|
|
|
|
|
print "At : ".$now->strftime('%Y/%m/%d %H:%M:%S')."\n"; |
60
|
|
|
|
|
|
|
print "Query : ".$queries->{$pid}->{query}."\n"; |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
sub search_queries { |
66
|
|
|
|
|
|
|
my ($self, $db) = @_; |
67
|
|
|
|
|
|
|
my @pids; |
68
|
|
|
|
|
|
|
my $queries = {}; |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
my $sth = $db->dbh->prepare(" |
71
|
|
|
|
|
|
|
SELECT |
72
|
|
|
|
|
|
|
datname, |
73
|
|
|
|
|
|
|
pid, |
74
|
|
|
|
|
|
|
query_start, |
75
|
|
|
|
|
|
|
state, |
76
|
|
|
|
|
|
|
query |
77
|
|
|
|
|
|
|
FROM |
78
|
|
|
|
|
|
|
pg_stat_activity |
79
|
|
|
|
|
|
|
WHERE |
80
|
|
|
|
|
|
|
pid <> pg_backend_pid() |
81
|
|
|
|
|
|
|
"); |
82
|
|
|
|
|
|
|
$sth->execute(); |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
while (my $hash_ref = $sth->fetchrow_hashref) { |
85
|
|
|
|
|
|
|
my %row = %$hash_ref; |
86
|
|
|
|
|
|
|
if($db->database ne $row{datname}) { |
87
|
|
|
|
|
|
|
next; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
if($self->match_state ne '' and $row{state} ne $self->match_state) { |
90
|
|
|
|
|
|
|
next; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
if($self->match_query ne '' and $row{query} !~ /$self->{match_query}/im ) { |
93
|
|
|
|
|
|
|
next; |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
if($self->ignore_match_state ne '' and $row{state} eq $self->ignore_match_state) { |
96
|
|
|
|
|
|
|
next; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
if($self->ignore_match_query ne '' and $row{query} =~ /$self->{ignore_match_query}/im ) { |
99
|
|
|
|
|
|
|
next; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
if($self->run_time != 0) { |
102
|
|
|
|
|
|
|
$qt = $qt_format->parse_datetime($row{query_start}); |
103
|
|
|
|
|
|
|
$qt->set_time_zone('local'); |
104
|
|
|
|
|
|
|
my $diff = $start_time->epoch() - $qt->epoch(); |
105
|
|
|
|
|
|
|
if($diff < $self->run_time) { |
106
|
|
|
|
|
|
|
next; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
my $tmp = { |
111
|
|
|
|
|
|
|
"datname" => $row{datname}, |
112
|
|
|
|
|
|
|
"pid" => $row{pid}, |
113
|
|
|
|
|
|
|
"query_start" => $row{query_start}, |
114
|
|
|
|
|
|
|
"state" => $row{state}, |
115
|
|
|
|
|
|
|
"query" => $row{query} |
116
|
|
|
|
|
|
|
}; |
117
|
|
|
|
|
|
|
my $q = Pgtools::Query->new($tmp); |
118
|
|
|
|
|
|
|
$queries = {%{$queries}, $row{pid} => $q}; |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
$sth->finish; |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
return $queries; |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
sub print_query { |
126
|
|
|
|
|
|
|
my $queries = shift @_; |
127
|
|
|
|
|
|
|
foreach my $q (keys(%$queries)) { |
128
|
|
|
|
|
|
|
print "-------------------------------\n"; |
129
|
|
|
|
|
|
|
print "pid : ".$queries->{$q}->{pid}."\n"; |
130
|
|
|
|
|
|
|
print "start_time: ".$queries->{$q}->{query_start}."\n"; |
131
|
|
|
|
|
|
|
print "state : ".$queries->{$q}->{state}."\n"; |
132
|
|
|
|
|
|
|
print "query : ".$queries->{$q}->{query}."\n"; |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
1; |