Filename | /usr/local/libexec/sympa/Sympa/LockedFile.pm |
Statements | Executed 23873 statements in 49.7ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1178 | 1 | 1 | 28.3ms | 398ms | open | Sympa::LockedFile::
1178 | 5 | 3 | 12.4ms | 105ms | DESTROY | Sympa::LockedFile::
2408 | 2 | 1 | 10.9ms | 10.9ms | __ANON__[:49] | Sympa::LockedFile::
1178 | 1 | 1 | 1.76ms | 1.76ms | CORE:match (opcode) | Sympa::LockedFile::
28 | 4 | 2 | 473µs | 7.46ms | close | Sympa::LockedFile::
0 | 0 | 0 | 0s | 0s | BEGIN@27 | Sympa::LockedFile::
0 | 0 | 0 | 0s | 0s | BEGIN@28 | Sympa::LockedFile::
0 | 0 | 0 | 0s | 0s | BEGIN@29 | Sympa::LockedFile::
0 | 0 | 0 | 0s | 0s | BEGIN@31 | Sympa::LockedFile::
0 | 0 | 0 | 0s | 0s | BEGIN@33 | Sympa::LockedFile::
0 | 0 | 0 | 0s | 0s | BEGIN@35 | Sympa::LockedFile::
0 | 0 | 0 | 0s | 0s | BEGIN@36 | Sympa::LockedFile::
0 | 0 | 0 | 0s | 0s | basename | Sympa::LockedFile::
0 | 0 | 0 | 0s | 0s | extend | Sympa::LockedFile::
0 | 0 | 0 | 0s | 0s | last_error | Sympa::LockedFile::
0 | 0 | 0 | 0s | 0s | rename | Sympa::LockedFile::
0 | 0 | 0 | 0s | 0s | unlink | Sympa::LockedFile::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # -*- indent-tabs-mode: nil; -*- | ||||
2 | # vim:ft=perl:et:sw=4 | ||||
3 | # $Id$ | ||||
4 | |||||
5 | # Sympa - SYsteme de Multi-Postage Automatique | ||||
6 | # | ||||
7 | # Copyright (c) 1997, 1998, 1999 Institut Pasteur & Christophe Wolfhugel | ||||
8 | # Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, | ||||
9 | # 2006, 2007, 2008, 2009, 2010, 2011 Comite Reseau des Universites | ||||
10 | # Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017 GIP RENATER | ||||
11 | # | ||||
12 | # This program is free software; you can redistribute it and/or modify | ||||
13 | # it under the terms of the GNU General Public License as published by | ||||
14 | # the Free Software Foundation; either version 2 of the License, or | ||||
15 | # (at your option) any later version. | ||||
16 | # | ||||
17 | # This program is distributed in the hope that it will be useful, | ||||
18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
20 | # GNU General Public License for more details. | ||||
21 | # | ||||
22 | # You should have received a copy of the GNU General Public License | ||||
23 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
24 | |||||
25 | package Sympa::LockedFile; | ||||
26 | |||||
27 | use strict; | ||||
28 | use warnings; | ||||
29 | use English qw(-no_match_vars); | ||||
30 | |||||
31 | use base qw(IO::File); | ||||
32 | |||||
33 | use File::NFSLock; | ||||
34 | |||||
35 | BEGIN { | ||||
36 | no warnings 'redefine'; | ||||
37 | |||||
38 | # Separate extensions with "," to avoid confusion with domain parts, | ||||
39 | # and to ensure that file names related to lock contains ",lock". | ||||
40 | $File::NFSLock::LOCK_EXTENSION = ',lock'; | ||||
41 | # spent 10.9ms within Sympa::LockedFile::__ANON__[/usr/local/libexec/sympa/Sympa/LockedFile.pm:49] which was called 2408 times, avg 5µs/call:
# 1204 times (6.32ms+0s) by File::NFSLock::new at line 126 of File/NFSLock.pm, avg 5µs/call
# 1204 times (4.61ms+0s) by File::NFSLock::uncache at line 432 of File/NFSLock.pm, avg 4µs/call | ||||
42 | 2408 | 671µs | my $file = shift; | ||
43 | return | ||||
44 | 2408 | 23.3ms | $file | ||
45 | . ',lock.' | ||||
46 | . time() % 10000 . '.' | ||||
47 | . $PID . '.' | ||||
48 | . int(rand() * 10000); | ||||
49 | }; | ||||
50 | } | ||||
51 | |||||
52 | our %lock_of; | ||||
53 | our $last_error; | ||||
54 | my $default_timeout = 30; | ||||
55 | my $stale_lock_timeout = 20 * 60; # TODO might become a config parameter | ||||
56 | |||||
57 | sub last_error { $last_error; } | ||||
58 | |||||
59 | # spent 398ms (28.3+370) within Sympa::LockedFile::open which was called 1178 times, avg 338µs/call:
# 1178 times (28.3ms+370ms) by IO::File::new at line 160 of IO/File.pm, avg 338µs/call | ||||
60 | 1178 | 257µs | my $self = shift; | ||
61 | 1178 | 304µs | my $file = shift; | ||
62 | 1178 | 400µs | my $blocking_timeout = shift || $default_timeout; | ||
63 | 1178 | 348µs | my $mode = shift || '<'; | ||
64 | |||||
65 | 1178 | 203µs | my $lock_type; | ||
66 | 1178 | 4.03ms | 1178 | 1.76ms | if ($mode =~ /[+>aw]/) { # spent 1.76ms making 1178 calls to Sympa::LockedFile::CORE:match, avg 1µs/call |
67 | $lock_type = File::NFSLock::LOCK_EX(); | ||||
68 | } else { | ||||
69 | 13 | 5µs | $lock_type = File::NFSLock::LOCK_SH(); | ||
70 | } | ||||
71 | 1178 | 663µs | if ($blocking_timeout < 0) { | ||
72 | $lock_type |= File::NFSLock::LOCK_NB(); | ||||
73 | } | ||||
74 | |||||
75 | 1178 | 346µs | undef $last_error; | ||
76 | |||||
77 | 1178 | 4.95ms | 1178 | 329ms | my $lock = File::NFSLock->new( # spent 329ms making 1178 calls to File::NFSLock::new, avg 280µs/call |
78 | { file => $file, | ||||
79 | lock_type => $lock_type, | ||||
80 | blocking_timeout => $blocking_timeout, | ||||
81 | stale_lock_timeout => $stale_lock_timeout, | ||||
82 | } | ||||
83 | ); | ||||
84 | 1178 | 267µs | unless ($lock) { | ||
85 | $last_error = $File::NFSLock::errstr || 'Unknown error'; | ||||
86 | return undef; | ||||
87 | } | ||||
88 | |||||
89 | 1178 | 712µs | if ($mode ne '+') { | ||
90 | 1178 | 1.96ms | 1178 | 38.7ms | unless ($self->SUPER::open($file, $mode)) { # spent 38.7ms making 1178 calls to IO::File::open, avg 33µs/call |
91 | $last_error = $ERRNO || 'Unknown error'; | ||||
92 | $lock->unlock; # make sure unlock to occur immediately. | ||||
93 | return undef; | ||||
94 | } | ||||
95 | } | ||||
96 | |||||
97 | 1178 | 1.74ms | $lock_of{$self + 0} = $lock; # register lock object, i.e. keep locking. | ||
98 | 1178 | 2.31ms | return 1; | ||
99 | } | ||||
100 | |||||
101 | # spent 7.46ms (473µs+6.98) within Sympa::LockedFile::close which was called 28 times, avg 266µs/call:
# 13 times (212µs+5.81ms) by Sympa::List::_load_list_config_file at line 5209 of /usr/local/libexec/sympa/Sympa/List.pm, avg 463µs/call
# 13 times (177µs+905µs) by Sympa::List::load at line 725 of /usr/local/libexec/sympa/Sympa/List.pm, avg 83µs/call
# once (65µs+194µs) by Sympa::Process::write_pid at line 371 of /usr/local/libexec/sympa/Sympa/Process.pm
# once (19µs+75µs) by Sympa::Process::remove_pid at line 283 of /usr/local/libexec/sympa/Sympa/Process.pm | ||||
102 | 28 | 9µs | my $self = shift; | ||
103 | |||||
104 | 28 | 7µs | my $ret; | ||
105 | 28 | 120µs | 56 | 287µs | if (defined $self->fileno) { # spent 231µs making 28 calls to IO::Handle::close, avg 8µs/call
# spent 56µs making 28 calls to IO::Handle::fileno, avg 2µs/call |
106 | $ret = $self->SUPER::close; | ||||
107 | } else { | ||||
108 | $ret = 1; | ||||
109 | } | ||||
110 | |||||
111 | 28 | 32µs | die 'Lock not found' unless exists $lock_of{$self + 0}; | ||
112 | |||||
113 | 28 | 52µs | 28 | 6.61ms | $lock_of{$self + 0}->unlock; # make sure unlock to occur immediately. # spent 6.61ms making 28 calls to File::NFSLock::unlock, avg 236µs/call |
114 | 28 | 132µs | 28 | 88µs | delete $lock_of{$self + 0}; # lock object will be destructed. # spent 88µs making 28 calls to File::NFSLock::DESTROY, avg 3µs/call |
115 | 28 | 62µs | return $ret; | ||
116 | } | ||||
117 | |||||
118 | sub extend { | ||||
119 | my $self = shift; | ||||
120 | |||||
121 | die 'Lock not fould' unless exists $lock_of{$self + 0}; | ||||
122 | |||||
123 | undef $last_error; | ||||
124 | unless (utime undef, undef, $lock_of{$self + 0}->{lock_file}) { | ||||
125 | $last_error = $ERRNO; | ||||
126 | return undef; | ||||
127 | } | ||||
128 | |||||
129 | return 1; | ||||
130 | } | ||||
131 | |||||
132 | sub basename { | ||||
133 | my $self = shift; | ||||
134 | my $level = shift || 0; | ||||
135 | |||||
136 | die 'Lock not found' unless exists $lock_of{$self + 0}; | ||||
137 | |||||
138 | my @paths = reverse split '/', $lock_of{$self + 0}->{file}; | ||||
139 | return $paths[$level]; | ||||
140 | } | ||||
141 | |||||
142 | sub rename { | ||||
143 | my $self = shift; | ||||
144 | my $destfile = shift; | ||||
145 | |||||
146 | die 'Lock not found' unless exists $lock_of{$self + 0}; | ||||
147 | |||||
148 | undef $last_error; | ||||
149 | my $lock = $lock_of{$self + 0}; | ||||
150 | |||||
151 | unless ($lock->{lock_type} & File::NFSLock::LOCK_EX()) { | ||||
152 | $last_error = 'Not the exclusive lock'; | ||||
153 | return undef; | ||||
154 | } | ||||
155 | |||||
156 | my $dest = (ref $self)->new($destfile, -1, '+') or return undef; | ||||
157 | if (defined $self->fileno) { | ||||
158 | $self->SUPER::close; | ||||
159 | } | ||||
160 | unless (rename $lock->{file}, $destfile) { | ||||
161 | my $error = $ERRNO; | ||||
162 | $dest->close; | ||||
163 | $last_error = $error; | ||||
164 | return undef; | ||||
165 | } | ||||
166 | $self->close; | ||||
167 | $dest->close; | ||||
168 | |||||
169 | return 1; | ||||
170 | } | ||||
171 | |||||
172 | sub unlink { | ||||
173 | my $self = shift; | ||||
174 | |||||
175 | die 'Lock not found' unless exists $lock_of{$self + 0}; | ||||
176 | |||||
177 | undef $last_error; | ||||
178 | if ($lock_of{$self + 0}->{file}) { | ||||
179 | unless (unlink $lock_of{$self + 0}->{file}) { | ||||
180 | $last_error = $ERRNO; | ||||
181 | return undef; | ||||
182 | } | ||||
183 | } | ||||
184 | |||||
185 | return $self->close; | ||||
186 | } | ||||
187 | |||||
188 | # Destruct inside reference to lock object so that it will be released. | ||||
189 | # Corresponding filehandle will be closed automatically. | ||||
190 | # spent 105ms (12.4+92.4) within Sympa::LockedFile::DESTROY which was called 1178 times, avg 89µs/call:
# 1150 times (12.3ms+92.4ms) by Sympa::Spool::next at line 155 of /usr/local/libexec/sympa/Sympa/Spool.pm, avg 91µs/call
# 13 times (35µs+0s) by Sympa::List::_load_list_config_file at line 5269 of /usr/local/libexec/sympa/Sympa/List.pm, avg 3µs/call
# 13 times (17µs+0s) by Sympa::List::load at line 725 of /usr/local/libexec/sympa/Sympa/List.pm, avg 1µs/call
# once (3µs+0s) by Sympa::Process::write_pid at line 373 of /usr/local/libexec/sympa/Sympa/Process.pm
# once (1µs+0s) by Sympa::Process::remove_pid at line 284 of /usr/local/libexec/sympa/Sympa/Process.pm | ||||
191 | 1178 | 239µs | my $self = shift; | ||
192 | 1178 | 6.55ms | 1150 | 92.4ms | delete $lock_of{$self + 0}; # lock object will be destructed. # spent 92.4ms making 1150 calls to File::NFSLock::DESTROY, avg 80µs/call |
193 | } | ||||
194 | |||||
195 | 1; | ||||
196 | __END__ | ||||
# spent 1.76ms within Sympa::LockedFile::CORE:match which was called 1178 times, avg 1µs/call:
# 1178 times (1.76ms+0s) by Sympa::LockedFile::open at line 66, avg 1µs/call |