line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package IPC::Transit::Internal; |
2
|
|
|
|
|
|
|
$IPC::Transit::Internal::VERSION = '1.162230'; |
3
|
16
|
|
|
16
|
|
49
|
use strict;use warnings; |
|
16
|
|
|
16
|
|
19
|
|
|
16
|
|
|
|
|
380
|
|
|
16
|
|
|
|
|
49
|
|
|
16
|
|
|
|
|
20
|
|
|
16
|
|
|
|
|
315
|
|
4
|
16
|
|
|
16
|
|
6334
|
use IPC::SysV; |
|
16
|
|
|
|
|
13573
|
|
|
16
|
|
|
|
|
612
|
|
5
|
16
|
|
|
16
|
|
6350
|
use IPC::Msg; |
|
16
|
|
|
|
|
56633
|
|
|
16
|
|
|
|
|
405
|
|
6
|
16
|
|
|
16
|
|
7211
|
use POSIX; |
|
16
|
|
|
|
|
75082
|
|
|
16
|
|
|
|
|
82
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
|
9
|
16
|
|
|
|
|
15757
|
use vars qw( |
10
|
|
|
|
|
|
|
$config |
11
|
16
|
|
|
16
|
|
34149
|
); |
|
16
|
|
|
|
|
24
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
{ |
14
|
|
|
|
|
|
|
my $queue_cache = {}; |
15
|
|
|
|
|
|
|
sub _initialize_queue { |
16
|
0
|
|
|
0
|
|
|
my %args = @_; |
17
|
0
|
|
|
|
|
|
my $qid = _get_queue_id(%args); |
18
|
0
|
0
|
|
|
|
|
if(not $queue_cache->{$qid}) { |
19
|
0
|
0
|
|
|
|
|
$queue_cache->{$qid} = IPC::Msg->new($qid, _get_flags('create_ipc')) |
20
|
|
|
|
|
|
|
or die "failed to _initialize_queue: failed to create queue_id $qid: $!\n"; |
21
|
|
|
|
|
|
|
} |
22
|
0
|
|
|
|
|
|
return $queue_cache->{$qid}; |
23
|
|
|
|
|
|
|
} |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub _remove { |
26
|
0
|
|
|
0
|
|
|
my %args = @_; |
27
|
0
|
|
|
|
|
|
my $qname = $args{qname}; |
28
|
0
|
|
|
|
|
|
my $qid = _get_queue_id(%args); |
29
|
0
|
0
|
|
|
|
|
$queue_cache->{$qid}->remove if $queue_cache->{$qid}; |
30
|
0
|
|
|
|
|
|
unlink _get_transit_config_dir() . "/$qname"; |
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
sub _stat { |
34
|
0
|
|
|
0
|
|
|
my %args = @_; |
35
|
0
|
|
|
|
|
|
my $qid = _get_queue_id(%args); |
36
|
0
|
|
|
|
|
|
_initialize_queue(%args); |
37
|
0
|
|
|
|
|
|
my @heads = qw(uid gid cuid cgid mode qnum qbytes lspid lrpid stime rtime ctime); |
38
|
0
|
|
|
|
|
|
my $ret = {}; |
39
|
0
|
|
|
|
|
|
my @items = @{$queue_cache->{$qid}->stat}; |
|
0
|
|
|
|
|
|
|
40
|
0
|
|
|
|
|
|
foreach my $item (@items) { |
41
|
0
|
|
|
|
|
|
$ret->{shift @heads} = $item; |
42
|
|
|
|
|
|
|
} |
43
|
0
|
|
|
|
|
|
$ret->{qname} = $args{qname}; |
44
|
0
|
|
|
|
|
|
$ret->{qid} = $qid; |
45
|
0
|
|
|
|
|
|
return $ret; |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
sub _drop_all_queues { |
50
|
0
|
|
|
0
|
|
|
foreach my $qname (keys %{$config->{queues}}) { |
|
0
|
|
|
|
|
|
|
51
|
0
|
|
|
|
|
|
_remove(qname => $qname); |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
sub _stats { |
55
|
0
|
|
|
0
|
|
|
my $ret = []; |
56
|
0
|
|
|
|
|
|
_gather_queue_info(); |
57
|
0
|
|
|
|
|
|
foreach my $queue_name (keys %{$config->{queues}}) { |
|
0
|
|
|
|
|
|
|
58
|
0
|
|
|
|
|
|
push @$ret, IPC::Transit::stat(qname => $queue_name); |
59
|
|
|
|
|
|
|
} |
60
|
0
|
|
|
|
|
|
return $ret; |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
sub _get_transit_config_dir { |
64
|
0
|
|
0
|
0
|
|
|
my $dir = $IPC::Transit::config_dir || '/tmp/ipc_transit/'; |
65
|
0
|
|
|
|
|
|
return $dir; |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
sub _lock_config_dir { |
69
|
0
|
|
|
0
|
|
|
my $lock_file = _get_transit_config_dir() . '/.lock'; |
70
|
0
|
|
|
|
|
|
my ($have_lock, $fh); |
71
|
0
|
|
|
|
|
|
for (1..2) { |
72
|
0
|
0
|
|
|
|
|
if(sysopen($fh, $lock_file, _get_flags('exclusive_lock'))) { |
73
|
0
|
|
|
|
|
|
$have_lock = 1; |
74
|
0
|
|
|
|
|
|
last; |
75
|
|
|
|
|
|
|
} |
76
|
0
|
|
|
|
|
|
sleep 1; |
77
|
|
|
|
|
|
|
} |
78
|
0
|
0
|
|
|
|
|
if(not $have_lock) { |
79
|
0
|
|
|
|
|
|
_unlock_config_dir(); |
80
|
0
|
|
|
|
|
|
sysopen($fh, $lock_file, _get_flags('exclusive_lock')); |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
#we have the advisory lock for sure now |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
sub _unlock_config_dir { |
87
|
0
|
|
|
0
|
|
|
my $lock_file = _get_transit_config_dir() . '/.lock'; |
88
|
0
|
0
|
|
|
|
|
unlink $lock_file or die "_unlock_config_dir: failed to unlink $lock_file: $!"; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
sub _gather_queue_info { |
92
|
0
|
|
|
0
|
|
|
_mk_queue_dir(); |
93
|
0
|
0
|
|
|
|
|
$config->{queues} = {} unless $config->{queues}; |
94
|
0
|
|
|
|
|
|
foreach my $filename (glob _get_transit_config_dir() . '/*') { |
95
|
0
|
|
|
|
|
|
my $info = {}; |
96
|
0
|
0
|
|
|
|
|
open my $fh, '<', $filename |
97
|
|
|
|
|
|
|
or die "IPC::Transit::Internal::_gather_queue_info: failed to open $filename for reading: $!"; |
98
|
0
|
|
|
|
|
|
while(my $line = <$fh>) { |
99
|
0
|
|
|
|
|
|
chomp $line; |
100
|
0
|
|
|
|
|
|
my ($key, $value) = split '=', $line; |
101
|
0
|
|
|
|
|
|
$info->{$key} = $value; |
102
|
|
|
|
|
|
|
} |
103
|
0
|
0
|
|
|
|
|
die 'required key "qid" not found' unless $info->{qid}; |
104
|
0
|
0
|
|
|
|
|
die 'required key "qname" not found' unless $info->{qname}; |
105
|
0
|
|
|
|
|
|
$config->{queues}->{$info->{qname}} = $info; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub _queue_exists { |
110
|
0
|
|
|
0
|
|
|
my $qname = shift; |
111
|
0
|
|
|
|
|
|
_mk_queue_dir(); |
112
|
0
|
|
|
|
|
|
return $config->{queues}->{$qname}; |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
sub _get_queue_id { |
116
|
0
|
|
|
0
|
|
|
my %args = @_; |
117
|
0
|
|
|
|
|
|
_mk_queue_dir(); |
118
|
0
|
|
|
|
|
|
my $qname = $args{qname}; |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
#return it if we have it |
121
|
|
|
|
|
|
|
return $config->{queues}->{$qname}->{qid} |
122
|
0
|
0
|
0
|
|
|
|
if $config->{queues} and $config->{queues}->{$qname}; |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
#we don't have it; let's load it and try again |
125
|
0
|
|
|
|
|
|
_gather_queue_info(); |
126
|
|
|
|
|
|
|
return $config->{queues}->{$qname}->{qid} |
127
|
0
|
0
|
0
|
|
|
|
if $config->{queues} and $config->{queues}->{$qname}; |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
#we still don't have it; get a lock, load it, try again, ane make |
130
|
|
|
|
|
|
|
#it if necessary |
131
|
0
|
|
|
|
|
|
_lock_config_dir(); |
132
|
0
|
|
|
|
|
|
eval { |
133
|
|
|
|
|
|
|
#now re-load the config |
134
|
0
|
|
|
|
|
|
_gather_queue_info(); |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
#if we now have it, unlock and return it |
137
|
0
|
0
|
0
|
|
|
|
if($config->{queues} and $config->{queues}->{$qname}) { |
138
|
0
|
|
|
|
|
|
_unlock_config_dir(); |
139
|
0
|
|
|
|
|
|
return $config->{queues}->{$qname}->{qid}; |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
#otherwise, we need to make one |
143
|
0
|
|
|
|
|
|
{ my $file = _get_transit_config_dir() . "/$qname"; |
|
0
|
|
|
|
|
|
|
144
|
0
|
0
|
|
|
|
|
open my $fh, '>', $file or die "IPC::Transit::Internal::_get_queue_id: failed to open $file for writing: $!"; |
145
|
0
|
|
|
|
|
|
my $new_qid = IPC::SysV::ftok($file, 1); |
146
|
0
|
|
|
|
|
|
print $fh "qid=$new_qid\n"; |
147
|
0
|
|
|
|
|
|
print $fh "qname=$qname\n"; |
148
|
0
|
|
|
|
|
|
close $fh; |
149
|
|
|
|
|
|
|
} |
150
|
0
|
|
|
|
|
|
_unlock_config_dir(); |
151
|
|
|
|
|
|
|
}; |
152
|
0
|
0
|
|
|
|
|
if($@) { |
153
|
0
|
|
|
|
|
|
_unlock_config_dir(); |
154
|
|
|
|
|
|
|
} |
155
|
0
|
|
|
|
|
|
_gather_queue_info(); |
156
|
0
|
|
|
|
|
|
return $config->{queues}->{$qname}->{qid}; |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
sub _mk_queue_dir { |
160
|
0
|
0
|
|
0
|
|
|
mkdir _get_transit_config_dir(), 0777 |
161
|
|
|
|
|
|
|
unless -d _get_transit_config_dir(); |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
#gnarly looking UNIX goop hidden below |
165
|
|
|
|
|
|
|
{ |
166
|
|
|
|
|
|
|
my $flags = { |
167
|
|
|
|
|
|
|
create_ipc => IPC::SysV::S_IRUSR() | |
168
|
|
|
|
|
|
|
IPC::SysV::S_IWUSR() | |
169
|
|
|
|
|
|
|
IPC::SysV::S_IRGRP() | |
170
|
|
|
|
|
|
|
IPC::SysV::S_IWGRP() | |
171
|
|
|
|
|
|
|
IPC::SysV::S_IROTH() | |
172
|
|
|
|
|
|
|
IPC::SysV::S_IWOTH() | |
173
|
|
|
|
|
|
|
IPC::SysV::IPC_CREAT(), |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
nowait => IPC::SysV::IPC_NOWAIT(), |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
exclusive_lock => POSIX::O_RDWR() | |
178
|
|
|
|
|
|
|
POSIX::O_CREAT() | |
179
|
|
|
|
|
|
|
POSIX::O_EXCL(), |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
nonblock => POSIX::O_NONBLOCK(), |
182
|
|
|
|
|
|
|
}; |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
sub |
185
|
|
|
|
|
|
|
_get_flags { |
186
|
0
|
|
|
0
|
|
|
my $name = shift; |
187
|
0
|
|
|
|
|
|
return $flags->{$name}; |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
1; |