line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package BGPmon::Fetch::File; |
2
|
|
|
|
|
|
|
our $VERSION = '2.0'; |
3
|
|
|
|
|
|
|
|
4
|
1
|
|
|
1
|
|
48995
|
use 5.14.0; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
46
|
|
5
|
1
|
|
|
1
|
|
5
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
29
|
|
6
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
28
|
|
7
|
1
|
|
|
1
|
|
893
|
use POSIX qw/strftime/; |
|
1
|
|
|
|
|
7501
|
|
|
1
|
|
|
|
|
9
|
|
8
|
1
|
|
|
1
|
|
740226
|
use IO::Uncompress::AnyUncompress qw(anyuncompress $AnyUncompressError); |
|
1
|
|
|
|
|
1904630
|
|
|
1
|
|
|
|
|
189
|
|
9
|
1
|
|
|
1
|
|
12
|
use File::Path qw/mkpath rmtree/; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
66
|
|
10
|
1
|
|
|
1
|
|
2342
|
use XML::LibXML::Reader; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
BEGIN{ |
13
|
|
|
|
|
|
|
require Exporter; |
14
|
|
|
|
|
|
|
our $AUTOLOAD; |
15
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
16
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( 'all' => [ qw(init_bgpdata connect_file |
17
|
|
|
|
|
|
|
read_xml_message close_connection is_connected messages_read uptime |
18
|
|
|
|
|
|
|
connection_endtime connection_duration get_error_code get_error_message |
19
|
|
|
|
|
|
|
get_error_msg) ] ); |
20
|
|
|
|
|
|
|
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
21
|
|
|
|
|
|
|
} |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
# connection status |
24
|
|
|
|
|
|
|
my $msgs_read = 0; |
25
|
|
|
|
|
|
|
my $connection_start; |
26
|
|
|
|
|
|
|
my $connection_stop; |
27
|
|
|
|
|
|
|
my $connected = 0; |
28
|
|
|
|
|
|
|
my $saw_start = 0; #saw_start and saw_end track tags |
29
|
|
|
|
|
|
|
my $saw_end = 0; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
#Set these to 1 to skip errors and/or incomplete data errors |
32
|
|
|
|
|
|
|
my $ignore_data_errors = 0; |
33
|
|
|
|
|
|
|
my $ignore_incomplete_data = 0; |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
#state variables to maintain state between calls to read_xml_message |
36
|
|
|
|
|
|
|
my $upd_fh; #filehandle for update files |
37
|
|
|
|
|
|
|
my $upd_filename; #Filename |
38
|
|
|
|
|
|
|
my $xml_reader; #variable to use as the XML reader |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
#scratch directory and default filename |
41
|
|
|
|
|
|
|
my $scratch_dir = "/tmp/"; |
42
|
|
|
|
|
|
|
my $output_file = "extract_bgp.$$"; |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
#Error codes and messages |
45
|
|
|
|
|
|
|
my %error_code; |
46
|
|
|
|
|
|
|
my %error_msg; |
47
|
|
|
|
|
|
|
my @function_names = ('init_bgpdata', 'connect_file', 'read_xml_message', |
48
|
|
|
|
|
|
|
'close_connection', 'is_connected', 'uptime', 'connection_endtime', |
49
|
|
|
|
|
|
|
'connection_duration'); |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
use constant NO_ERROR_CODE => 0; |
52
|
|
|
|
|
|
|
use constant NO_ERROR_MSG => 'No Error'; |
53
|
|
|
|
|
|
|
use constant UNDEFINED_ARGUMENT_CODE => 301; |
54
|
|
|
|
|
|
|
use constant UNDEFINED_ARGUMENT_MSG => 'Undefined Argument(s)'; |
55
|
|
|
|
|
|
|
use constant UNCONNECTED_CODE => 302; |
56
|
|
|
|
|
|
|
use constant UNCONNECTED_MSG => 'Not connected to a file'; |
57
|
|
|
|
|
|
|
use constant ALREADY_CONNECTED_CODE => 303; |
58
|
|
|
|
|
|
|
use constant ALREADY_CONNECTED_MSG => 'Already connected to a file'; |
59
|
|
|
|
|
|
|
use constant NO_SUCH_FILE_CODE => 304; |
60
|
|
|
|
|
|
|
use constant NO_SUCH_FILE_MSG => 'Specified file/directory does not exist'; |
61
|
|
|
|
|
|
|
use constant SYSCALL_FAIL_CODE => 305; |
62
|
|
|
|
|
|
|
use constant SYSCALL_FAIL_MSG => 'System call failed'; |
63
|
|
|
|
|
|
|
use constant DECOMPRESS_FAIL_CODE => 306; |
64
|
|
|
|
|
|
|
use constant DECOMPRESS_FAIL_MSG => 'Failed to decompress file'; |
65
|
|
|
|
|
|
|
use constant OPEN_FAIL_CODE => 307; |
66
|
|
|
|
|
|
|
use constant OPEN_FAIL_MSG => 'Failed to open file'; |
67
|
|
|
|
|
|
|
use constant PARSER_INIT_FAIL_CODE => 308; |
68
|
|
|
|
|
|
|
use constant PARSER_INIT_FAIL_MSG => 'Failed to initialize XML Reader'; |
69
|
|
|
|
|
|
|
use constant PARSER_FATAL_ERROR_CODE => 309; |
70
|
|
|
|
|
|
|
use constant PARSER_FATAL_ERROR_MSG => 'XML Parser Error'; |
71
|
|
|
|
|
|
|
use constant FILE_FORMAT_ERROR_CODE => 310; |
72
|
|
|
|
|
|
|
use constant FILE_FORMAT_ERROR_MSG => 'File must begin with tag'; |
73
|
|
|
|
|
|
|
use constant INVALID_FUNCTION_SPECIFIED_CODE => 311; |
74
|
|
|
|
|
|
|
use constant INVALID_FUNCTION_SPECIFIED_MSG => 'Invalid function specified'; |
75
|
|
|
|
|
|
|
use constant INIT_FAIL_CODE => 312; |
76
|
|
|
|
|
|
|
use constant INIT_FAIL_MSG => 'Failed to initialize file connection'; |
77
|
|
|
|
|
|
|
use constant INCOMPLETE_DATA_CODE => 313; |
78
|
|
|
|
|
|
|
use constant INCOMPLETE_DATA_MSG => |
79
|
|
|
|
|
|
|
'File is missing expected ARCHIVER messages'; |
80
|
|
|
|
|
|
|
use constant DATA_GAP_CODE => 314; |
81
|
|
|
|
|
|
|
use constant DATA_GAP_MSG => 'File may be missing data'; |
82
|
|
|
|
|
|
|
use constant IGNORE_ERROR_CODE => 315; |
83
|
|
|
|
|
|
|
use constant IGNORE_ERROR_MSG => |
84
|
|
|
|
|
|
|
'Cannot have ignore_incomplete_data off with ignore_data_errors on'; |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
for my $function_name (@function_names) { |
87
|
|
|
|
|
|
|
$error_code{$function_name} = NO_ERROR_CODE; |
88
|
|
|
|
|
|
|
$error_msg{$function_name} = NO_ERROR_MSG; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
END{ |
92
|
|
|
|
|
|
|
my $errs; |
93
|
|
|
|
|
|
|
rmtree($scratch_dir,{keep_root => 1, safe => 1, error => \$errs}); |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=head1 NAME |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
BGPmon::Fetch::File |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
The BGPmon::Fetch::File module, to connect to a local XML file and read |
101
|
|
|
|
|
|
|
XML messages one at a time. |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=head1 SYNOPSIS |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
The BGPmon::Fetch::File module provides functionality to connect |
107
|
|
|
|
|
|
|
to an XML file and read message at a time. |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
use BGPmon::Fetch::File; |
110
|
|
|
|
|
|
|
my $ret = init_bgpdata('scratch_dir'=>'path/to/temp/dir', |
111
|
|
|
|
|
|
|
'ignore_incomplete_data' => 0, 'ignore_data_errors' => 0); |
112
|
|
|
|
|
|
|
my $ret = connect_file('path/to/file'); |
113
|
|
|
|
|
|
|
my $xml_msg = read_xml_message(); |
114
|
|
|
|
|
|
|
my $ret = is_connected(); |
115
|
|
|
|
|
|
|
my $num_read = messages_read(); |
116
|
|
|
|
|
|
|
my $uptime = uptime(); |
117
|
|
|
|
|
|
|
my $ret = close_connection(); |
118
|
|
|
|
|
|
|
my $downtime = connection_endtime(); |
119
|
|
|
|
|
|
|
my $duration = connection_duration(); |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
=head1 EXPORT |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
init_bgpdata |
124
|
|
|
|
|
|
|
connect_file |
125
|
|
|
|
|
|
|
read_xml_message |
126
|
|
|
|
|
|
|
close_connection |
127
|
|
|
|
|
|
|
is_connected |
128
|
|
|
|
|
|
|
messages_read |
129
|
|
|
|
|
|
|
uptime |
130
|
|
|
|
|
|
|
connection_endtime |
131
|
|
|
|
|
|
|
connection_duration |
132
|
|
|
|
|
|
|
get_error_code |
133
|
|
|
|
|
|
|
get_error_message |
134
|
|
|
|
|
|
|
get_error_msg |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=cut |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=head1 SUBROUTINES/METHODS |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=head2 init_bgpdata |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
Initializes the scratch directory and error-checking flags for the next |
143
|
|
|
|
|
|
|
file connection. |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
Input: The location to create a scratch directory in (default is /tmp) |
146
|
|
|
|
|
|
|
Whether to ignore potentially incomplete data (default is off) |
147
|
|
|
|
|
|
|
Whether to ignore all data errors (must also specify ignore |
148
|
|
|
|
|
|
|
incomplete data flag as well) (default is off) |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
Output: 0 if initialization fails |
151
|
|
|
|
|
|
|
1 if initialization succeeds |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
Usage: my $ret = init_bgpdata('scratch_dir' => '/tmp', |
154
|
|
|
|
|
|
|
'ignore_incomplete_data' => 1, 'ignore_data_errors' => 0); |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
=cut |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
sub init_bgpdata{ |
159
|
|
|
|
|
|
|
my %args = @_; |
160
|
|
|
|
|
|
|
my $fname = "init_bgpdata"; |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
#Extract the specified scratch directory if specified, otherwise |
163
|
|
|
|
|
|
|
#use the default directory (/tmp). |
164
|
|
|
|
|
|
|
my $new_dir = $args{'scratch_dir'}; |
165
|
|
|
|
|
|
|
if( !defined($new_dir) ){ |
166
|
|
|
|
|
|
|
eval{ |
167
|
|
|
|
|
|
|
$scratch_dir .= "/BGP.File.$$"; |
168
|
|
|
|
|
|
|
$scratch_dir =~ s/\/\//\//; |
169
|
|
|
|
|
|
|
mkpath $scratch_dir; |
170
|
|
|
|
|
|
|
1; |
171
|
|
|
|
|
|
|
} or do { |
172
|
|
|
|
|
|
|
$error_code{$fname} = SYSCALL_FAIL_CODE; |
173
|
|
|
|
|
|
|
$error_msg{$fname} = SYSCALL_FAIL_MSG.": $@"; |
174
|
|
|
|
|
|
|
return 0; |
175
|
|
|
|
|
|
|
}; |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
else{ |
178
|
|
|
|
|
|
|
eval{ |
179
|
|
|
|
|
|
|
$new_dir .= "/BGP.File.$$"; |
180
|
|
|
|
|
|
|
$new_dir =~ s/\/\//\//; |
181
|
|
|
|
|
|
|
mkpath $new_dir; |
182
|
|
|
|
|
|
|
$scratch_dir = $new_dir; |
183
|
|
|
|
|
|
|
1; |
184
|
|
|
|
|
|
|
} or do { |
185
|
|
|
|
|
|
|
$error_code{$fname} = SYSCALL_FAIL_CODE; |
186
|
|
|
|
|
|
|
$error_msg{$fname} = SYSCALL_FAIL_MSG.": $@"; |
187
|
|
|
|
|
|
|
return 0; |
188
|
|
|
|
|
|
|
}; |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
#Get whether the user wants to ignore incomplete data or all data errors |
192
|
|
|
|
|
|
|
#It is an error to ignore all data errors but not incomplete data |
193
|
|
|
|
|
|
|
$ignore_incomplete_data = $args{'ignore_incomplete_data'} |
194
|
|
|
|
|
|
|
if defined $args{'ignore_incomplete_data'}; |
195
|
|
|
|
|
|
|
$ignore_data_errors = $args{'ignore_data_errors'} |
196
|
|
|
|
|
|
|
if defined $args{'ignore_data_errors'}; |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
if( $ignore_data_errors && !$ignore_incomplete_data ){ |
199
|
|
|
|
|
|
|
$error_code{$fname} = IGNORE_ERROR_CODE; |
200
|
|
|
|
|
|
|
$error_msg{$fname} = IGNORE_ERROR_MSG; |
201
|
|
|
|
|
|
|
return 0; |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
#Reset some module state variables, including error codes |
204
|
|
|
|
|
|
|
$saw_start = 0; |
205
|
|
|
|
|
|
|
$saw_end = 0; |
206
|
|
|
|
|
|
|
for my $function_name (@function_names) { |
207
|
|
|
|
|
|
|
$error_code{$function_name} = NO_ERROR_CODE; |
208
|
|
|
|
|
|
|
$error_msg{$function_name} = NO_ERROR_MSG; |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
$connection_stop = undef; |
211
|
|
|
|
|
|
|
return 1; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=head2 connect_file |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
This function connects to a local file. |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
Input: the filename to read XML from |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
Output: 0 on success, 1 on failure |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
Usage: my $ret = connect_file("path/to/file"); |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=cut |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub connect_file { |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
#Store arguments in state variables |
229
|
|
|
|
|
|
|
my $filename = shift; |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
my $fname = "connect_file"; |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
#Check for correct number of variables |
234
|
|
|
|
|
|
|
if( !defined($filename) ){ |
235
|
|
|
|
|
|
|
$error_code{$fname} = UNDEFINED_ARGUMENT_CODE; |
236
|
|
|
|
|
|
|
$error_msg{$fname} = UNDEFINED_ARGUMENT_MSG; |
237
|
|
|
|
|
|
|
return 1; |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
#We cannot connect to a file while already connected to one |
241
|
|
|
|
|
|
|
if(is_connected()){ |
242
|
|
|
|
|
|
|
$error_code{$fname} = ALREADY_CONNECTED_CODE; |
243
|
|
|
|
|
|
|
$error_msg{$fname} = ALREADY_CONNECTED_MSG; |
244
|
|
|
|
|
|
|
return 1; |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
#The file must exist before we can connect to it |
248
|
|
|
|
|
|
|
if(!file_check($filename) ){ |
249
|
|
|
|
|
|
|
$error_code{$fname} = NO_SUCH_FILE_CODE; |
250
|
|
|
|
|
|
|
$error_msg{$fname} = NO_SUCH_FILE_MSG; |
251
|
|
|
|
|
|
|
return 1; |
252
|
|
|
|
|
|
|
} |
253
|
|
|
|
|
|
|
#Create the scratch directory if it has not already been created |
254
|
|
|
|
|
|
|
#This call will create the default scratch directory, and will NOT |
255
|
|
|
|
|
|
|
#ignore any data errors |
256
|
|
|
|
|
|
|
if( $scratch_dir !~ m/BGP.File/ ){ |
257
|
|
|
|
|
|
|
if(!init_bgpdata('ignore_incomplete_data' => 0, |
258
|
|
|
|
|
|
|
'ignore_data_errors' => 0)){ |
259
|
|
|
|
|
|
|
$error_code{$fname} = INIT_FAIL_CODE; |
260
|
|
|
|
|
|
|
$error_msg{$fname} = INIT_FAIL_MSG; |
261
|
|
|
|
|
|
|
close_connection(); |
262
|
|
|
|
|
|
|
return 1; |
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
#decompress_file never fails to return |
266
|
|
|
|
|
|
|
my $ret = decompress_file($filename); |
267
|
|
|
|
|
|
|
$filename = $ret if defined $ret; |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
#Now open the now-uncompressed file |
270
|
|
|
|
|
|
|
unless( open($upd_fh, "<", "$scratch_dir/$filename") ){ |
271
|
|
|
|
|
|
|
$error_code{$fname} = OPEN_FAIL_CODE; |
272
|
|
|
|
|
|
|
$error_msg{$fname} = OPEN_FAIL_MSG.": $@"; |
273
|
|
|
|
|
|
|
return 1; |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
#Instantiate the XML parser |
277
|
|
|
|
|
|
|
unless($xml_reader = |
278
|
|
|
|
|
|
|
XML::LibXML::Reader->new(IO => $upd_fh, recover => 1)){ |
279
|
|
|
|
|
|
|
$error_code{$fname} = PARSER_INIT_FAIL_CODE; |
280
|
|
|
|
|
|
|
$error_msg{$fname} = PARSER_INIT_FAIL_MSG; |
281
|
|
|
|
|
|
|
close($upd_fh); |
282
|
|
|
|
|
|
|
return 1; |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
#We require all files to start w/ an tag; fail if it is not present. |
286
|
|
|
|
|
|
|
eval{ |
287
|
|
|
|
|
|
|
unless( $xml_reader->read() == 1 && $xml_reader->localName() eq "xml"){ |
288
|
|
|
|
|
|
|
$error_code{$fname} = FILE_FORMAT_ERROR_CODE; |
289
|
|
|
|
|
|
|
$error_msg{$fname} = FILE_FORMAT_ERROR_MSG; |
290
|
|
|
|
|
|
|
close($upd_fh); |
291
|
|
|
|
|
|
|
return 1; |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
1; |
294
|
|
|
|
|
|
|
} or do{ |
295
|
|
|
|
|
|
|
$error_code{$fname} = PARSER_FATAL_ERROR_CODE; |
296
|
|
|
|
|
|
|
$error_msg{$fname} = PARSER_FATAL_ERROR_MSG.": $@"; |
297
|
|
|
|
|
|
|
close($upd_fh); |
298
|
|
|
|
|
|
|
return 1; |
299
|
|
|
|
|
|
|
}; |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
#Now that we have successfully connected, set remaining state variables |
302
|
|
|
|
|
|
|
#for this connection |
303
|
|
|
|
|
|
|
$msgs_read = 0; |
304
|
|
|
|
|
|
|
$upd_filename = "$scratch_dir/$filename"; |
305
|
|
|
|
|
|
|
$connected = 1; |
306
|
|
|
|
|
|
|
$connection_start = time; |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
$error_code{$fname} = NO_ERROR_CODE; |
309
|
|
|
|
|
|
|
$error_msg{$fname} = NO_ERROR_MSG; |
310
|
|
|
|
|
|
|
return 0; |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
=head2 read_xml_message |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
This function reads one XML message at a time from an open file connection. |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
Input: None, but assumes connect_file has been called |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
Output: The next available XML message from the file, or undef if the |
320
|
|
|
|
|
|
|
messages are exhausted or some other failure is encountered |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
Usage: my $next_msg = read_xml_message(); |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
=cut |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
sub read_xml_message { |
327
|
|
|
|
|
|
|
my $fname = "read_xml_message"; |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
#There must be an open file connection to read from |
330
|
|
|
|
|
|
|
if( !is_connected() ){ |
331
|
|
|
|
|
|
|
$error_code{$fname} = UNCONNECTED_CODE; |
332
|
|
|
|
|
|
|
$error_msg{$fname} = UNCONNECTED_MSG; |
333
|
|
|
|
|
|
|
return undef; |
334
|
|
|
|
|
|
|
} |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
#The file that we're supposed to be connected to had better still be there |
337
|
|
|
|
|
|
|
if( !file_check($upd_filename) ){ |
338
|
|
|
|
|
|
|
$error_code{$fname} = NO_SUCH_FILE_CODE; |
339
|
|
|
|
|
|
|
$error_msg{$fname} = NO_SUCH_FILE_MSG; |
340
|
|
|
|
|
|
|
close_connection(); |
341
|
|
|
|
|
|
|
return undef; |
342
|
|
|
|
|
|
|
} |
343
|
|
|
|
|
|
|
my $complete_xml_msg = ""; |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
#For archive files, the root node (depth 0) is the tag |
346
|
|
|
|
|
|
|
#Therefore we want every XML message right under that (at depth 1) |
347
|
|
|
|
|
|
|
#These are mostly s, but could be anything |
348
|
|
|
|
|
|
|
while( $xml_reader->depth() != 1 || $xml_reader->nodeType() == |
349
|
|
|
|
|
|
|
XML_READER_TYPE_SIGNIFICANT_WHITESPACE){ |
350
|
|
|
|
|
|
|
#First try to read the next node in the XML stream |
351
|
|
|
|
|
|
|
#If the XML parser itself fails, close the connection and return |
352
|
|
|
|
|
|
|
eval{ |
353
|
|
|
|
|
|
|
#If read() returns 0, then we are at the end of the file |
354
|
|
|
|
|
|
|
#and we need to check for any data error. However, the XML parser |
355
|
|
|
|
|
|
|
#can fail too, so this eval will catch both cases which we need |
356
|
|
|
|
|
|
|
#to differentiate in the do block. |
357
|
|
|
|
|
|
|
return undef if !$xml_reader->read(); |
358
|
|
|
|
|
|
|
1; |
359
|
|
|
|
|
|
|
} or do { |
360
|
|
|
|
|
|
|
#This case catches any XML parser error. |
361
|
|
|
|
|
|
|
if($?){ |
362
|
|
|
|
|
|
|
$error_code{$fname} = PARSER_FATAL_ERROR_CODE; |
363
|
|
|
|
|
|
|
$error_msg{$fname} = PARSER_FATAL_ERROR_MSG.": $@"; |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
#Since the only other way to get into this block is for the file |
366
|
|
|
|
|
|
|
#to be done, this checks to make sure the file ended with an |
367
|
|
|
|
|
|
|
#ARCHIVER/CLOSED message (if we're looking for such things). |
368
|
|
|
|
|
|
|
elsif( $ignore_incomplete_data || $saw_end == 1 ){ |
369
|
|
|
|
|
|
|
$error_code{$fname} = NO_ERROR_CODE; |
370
|
|
|
|
|
|
|
$error_msg{$fname} = NO_ERROR_MSG; |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
#If the ARCHIVER/CLOSED message was not there or there were |
373
|
|
|
|
|
|
|
#more than 1, there is an error. |
374
|
|
|
|
|
|
|
else{ |
375
|
|
|
|
|
|
|
$error_code{$fname} = INCOMPLETE_DATA_CODE; |
376
|
|
|
|
|
|
|
$error_msg{$fname} = INCOMPLETE_DATA_MSG; |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
#All 3 cases terminate this connection. |
379
|
|
|
|
|
|
|
close_connection(); |
380
|
|
|
|
|
|
|
return undef; |
381
|
|
|
|
|
|
|
}; |
382
|
|
|
|
|
|
|
} |
383
|
|
|
|
|
|
|
eval{ |
384
|
|
|
|
|
|
|
$complete_xml_msg .= $xml_reader->readOuterXml(); |
385
|
|
|
|
|
|
|
#There are a couple of error cases to check w.r.t. ARCHIVER messages. |
386
|
|
|
|
|
|
|
#We must start off with an ARCHIVER/OPENED message |
387
|
|
|
|
|
|
|
#Any additional ARCHIVER/OPENED messages indicate missing data |
388
|
|
|
|
|
|
|
#We must see an ARCHIVER/END message |
389
|
|
|
|
|
|
|
if( !$ignore_data_errors && $xml_reader->localName() eq "ARCHIVER" && |
390
|
|
|
|
|
|
|
$xml_reader->nextElement("EVENT") == 1 ){ |
391
|
|
|
|
|
|
|
#This block examines any ARCHIVER messages we encounter. |
392
|
|
|
|
|
|
|
#If the current message is an ARCHIVER/OPENED and we have not seen |
393
|
|
|
|
|
|
|
#any messages yet, then it is expected and we can set the flag |
394
|
|
|
|
|
|
|
#to indicate it. |
395
|
|
|
|
|
|
|
if($xml_reader->readInnerXml() eq "OPENED" && $msgs_read == 0){ |
396
|
|
|
|
|
|
|
$saw_start = 1; |
397
|
|
|
|
|
|
|
$error_code{$fname} = NO_ERROR_CODE; |
398
|
|
|
|
|
|
|
$error_msg{$fname} = NO_ERROR_MSG; |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
#If the current message is an ARCHIVER/CLOSED message, then we |
401
|
|
|
|
|
|
|
#increment the count of such messages we've seen. This will be |
402
|
|
|
|
|
|
|
#used later in error-detection. |
403
|
|
|
|
|
|
|
elsif( $xml_reader->readInnerXml() eq "CLOSED" ){ |
404
|
|
|
|
|
|
|
$saw_end++; |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
#This case implies that the current message is an ARCHIVER/OPENED |
407
|
|
|
|
|
|
|
#message, but we've already seen one, so this is an error |
408
|
|
|
|
|
|
|
else{ return undef;} |
409
|
|
|
|
|
|
|
#Read to the beginning of the next XML message |
410
|
|
|
|
|
|
|
$xml_reader->read() while( $xml_reader->depth() != 1 || |
411
|
|
|
|
|
|
|
$xml_reader->nodeType() == XML_READER_TYPE_SIGNIFICANT_WHITESPACE ); |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
1; |
414
|
|
|
|
|
|
|
#This block handles the error cases that can arise from the previous |
415
|
|
|
|
|
|
|
#block. This can happen in two ways: either we've seen a duplicate |
416
|
|
|
|
|
|
|
#ARCHIVER/OPENED message or the XML parser itself failed. |
417
|
|
|
|
|
|
|
} or do { |
418
|
|
|
|
|
|
|
if( $msgs_read != 0 ){ |
419
|
|
|
|
|
|
|
$error_code{$fname} = DATA_GAP_CODE; |
420
|
|
|
|
|
|
|
$error_msg{$fname} = DATA_GAP_MSG; |
421
|
|
|
|
|
|
|
#We only want to throw this error if we care about |
422
|
|
|
|
|
|
|
#incomplete data. |
423
|
|
|
|
|
|
|
if( !$ignore_incomplete_data ){ |
424
|
|
|
|
|
|
|
close_connection(); |
425
|
|
|
|
|
|
|
return undef; |
426
|
|
|
|
|
|
|
} |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
else{ |
429
|
|
|
|
|
|
|
$error_code{$fname} = PARSER_FATAL_ERROR_CODE; |
430
|
|
|
|
|
|
|
$error_msg{$fname} = PARSER_FATAL_ERROR_MSG.": $@"; |
431
|
|
|
|
|
|
|
close_connection(); |
432
|
|
|
|
|
|
|
return undef; |
433
|
|
|
|
|
|
|
} |
434
|
|
|
|
|
|
|
}; |
435
|
|
|
|
|
|
|
if( !defined($complete_xml_msg) ){ |
436
|
|
|
|
|
|
|
$error_code{$fname} = FILE_FORMAT_ERROR_CODE; |
437
|
|
|
|
|
|
|
$error_msg{$fname} = FILE_FORMAT_ERROR_MSG.": $@"; |
438
|
|
|
|
|
|
|
close_connection(); |
439
|
|
|
|
|
|
|
return undef; |
440
|
|
|
|
|
|
|
} |
441
|
|
|
|
|
|
|
$xml_reader->next(); |
442
|
|
|
|
|
|
|
#If we are checking data errors, then the first message MUST |
443
|
|
|
|
|
|
|
#be an ARCHIVER/OPENED message, otherwise throw the error and quit. |
444
|
|
|
|
|
|
|
if( $msgs_read == 0 && !$saw_start && !$ignore_data_errors){ |
445
|
|
|
|
|
|
|
$error_code{$fname} = INCOMPLETE_DATA_CODE; |
446
|
|
|
|
|
|
|
$error_msg{$fname} = INCOMPLETE_DATA_MSG; |
447
|
|
|
|
|
|
|
close_connection(); |
448
|
|
|
|
|
|
|
return undef; |
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
$msgs_read++; |
451
|
|
|
|
|
|
|
$error_code{$fname} = NO_ERROR_CODE; |
452
|
|
|
|
|
|
|
$error_msg{$fname} = NO_ERROR_MSG; |
453
|
|
|
|
|
|
|
return $complete_xml_msg; |
454
|
|
|
|
|
|
|
} |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
=head2 close_connection |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
Function to close and delete any files and reset the module's state variables |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
Usage: close_connection(); |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
=cut |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
sub close_connection { |
466
|
|
|
|
|
|
|
my $fname = "close_connection"; |
467
|
|
|
|
|
|
|
#Can't close a connection that isn't there... |
468
|
|
|
|
|
|
|
if( !is_connected() ){ |
469
|
|
|
|
|
|
|
$error_code{$fname} = UNCONNECTED_CODE; |
470
|
|
|
|
|
|
|
$error_msg{$fname} = UNCONNECTED_MSG; |
471
|
|
|
|
|
|
|
return 1; |
472
|
|
|
|
|
|
|
} |
473
|
|
|
|
|
|
|
#Close the XML reader |
474
|
|
|
|
|
|
|
$xml_reader->close(); |
475
|
|
|
|
|
|
|
#Close the open file handle |
476
|
|
|
|
|
|
|
close($upd_fh) if defined(fileno $upd_fh); |
477
|
|
|
|
|
|
|
#Track the end of this connection |
478
|
|
|
|
|
|
|
$connection_stop = time; |
479
|
|
|
|
|
|
|
#Now try to delete the scratch directory; set an error if it fails |
480
|
|
|
|
|
|
|
#but do not return an error if the system call fails |
481
|
|
|
|
|
|
|
eval{ |
482
|
|
|
|
|
|
|
my $errs; |
483
|
|
|
|
|
|
|
rmtree($scratch_dir,{keep_root => 1, safe => 1, error => \$errs}); |
484
|
|
|
|
|
|
|
1; |
485
|
|
|
|
|
|
|
} or do { |
486
|
|
|
|
|
|
|
$error_code{$fname} = SYSCALL_FAIL_CODE; |
487
|
|
|
|
|
|
|
$error_msg{$fname} = SYSCALL_FAIL_MSG.": $@"; |
488
|
|
|
|
|
|
|
}; |
489
|
|
|
|
|
|
|
($upd_fh,$upd_filename) = undef; |
490
|
|
|
|
|
|
|
$error_code{$fname} = NO_ERROR_CODE; |
491
|
|
|
|
|
|
|
$error_msg{$fname} = NO_ERROR_MSG; |
492
|
|
|
|
|
|
|
$connected = 0; |
493
|
|
|
|
|
|
|
} |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
=head2 is_connected |
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
Function to report whether currently connected to an archive. |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
=cut |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
sub is_connected { |
502
|
|
|
|
|
|
|
return $connected; |
503
|
|
|
|
|
|
|
} |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
=head2 messages_read |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
Get number of messages read. |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
Usage: my $msgs_read = messages_read(); |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
=cut |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
sub messages_read { |
514
|
|
|
|
|
|
|
return $msgs_read; |
515
|
|
|
|
|
|
|
} |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
=head2 uptime |
518
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
Returns number of seconds the connection has been up. |
520
|
|
|
|
|
|
|
If the connection is down, return 0. |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
Usage: my $uptime = uptime(); |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
=cut |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
sub uptime { |
527
|
|
|
|
|
|
|
if ($connected) { |
528
|
|
|
|
|
|
|
return time() - $connection_start; |
529
|
|
|
|
|
|
|
} |
530
|
|
|
|
|
|
|
return 0; |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
} |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
=head2 connection_endtime |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
Returns the time the connection ended . |
537
|
|
|
|
|
|
|
If the connection is up, return 0. |
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
Usage: my $endtime = connection_endtime(); |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
=cut |
542
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
sub connection_endtime { |
544
|
|
|
|
|
|
|
my $fname = "connection_endtime"; |
545
|
|
|
|
|
|
|
if ($connected) { |
546
|
|
|
|
|
|
|
$error_code{$fname} = ALREADY_CONNECTED_CODE; |
547
|
|
|
|
|
|
|
$error_msg{$fname} = ALREADY_CONNECTED_MSG; |
548
|
|
|
|
|
|
|
return 0; |
549
|
|
|
|
|
|
|
} |
550
|
|
|
|
|
|
|
$error_code{$fname} = NO_ERROR_CODE; |
551
|
|
|
|
|
|
|
$error_msg{$fname} = NO_ERROR_MSG; |
552
|
|
|
|
|
|
|
return $connection_stop; |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
} |
555
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
=head2 connection_duration |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
Returns the total time the last connection was up for. |
559
|
|
|
|
|
|
|
If the connection is up, returns 0. |
560
|
|
|
|
|
|
|
NOTE: If a connection is currently established, call uptime(). |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
Usage: my $dur = connection_duration(); |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
=cut |
565
|
|
|
|
|
|
|
sub connection_duration{ |
566
|
|
|
|
|
|
|
my $fname = "connection_duration"; |
567
|
|
|
|
|
|
|
if( $connected) { |
568
|
|
|
|
|
|
|
$error_code{$fname} = ALREADY_CONNECTED_CODE; |
569
|
|
|
|
|
|
|
$error_msg{$fname} = ALREADY_CONNECTED_MSG; |
570
|
|
|
|
|
|
|
return 0; |
571
|
|
|
|
|
|
|
} |
572
|
|
|
|
|
|
|
$error_code{$fname} = NO_ERROR_CODE; |
573
|
|
|
|
|
|
|
$error_msg{$fname} = NO_ERROR_MSG; |
574
|
|
|
|
|
|
|
return $connection_stop - $connection_start; |
575
|
|
|
|
|
|
|
} |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
=head2 get_error_code |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
Get the error code |
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
Input : the name of the function whose error code we should report |
582
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
Output: the function's error code |
584
|
|
|
|
|
|
|
or UNDEFINED_ARGUMENT if the user did not supply a function |
585
|
|
|
|
|
|
|
or INVALID_FUNCTION_SPECIFIED if the user provided an invalid |
586
|
|
|
|
|
|
|
function name |
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
Usage: my $err_code = get_error_code("connect_file"); |
589
|
|
|
|
|
|
|
=cut |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
sub get_error_code { |
592
|
|
|
|
|
|
|
my $function = shift; |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
# check we got a function name |
595
|
|
|
|
|
|
|
if (!defined($function)) { |
596
|
|
|
|
|
|
|
return UNDEFINED_ARGUMENT_CODE; |
597
|
|
|
|
|
|
|
} |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
return $error_code{$function} if defined($error_code{$function}); |
600
|
|
|
|
|
|
|
return INVALID_FUNCTION_SPECIFIED_CODE; |
601
|
|
|
|
|
|
|
} |
602
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
=head2 get_error_message |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
Get the error message |
606
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
Input : the name of the function whose error message we should report |
608
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
Output: the function's error message |
610
|
|
|
|
|
|
|
or UNDEFINED_ARGUMENT if the user did not supply a function |
611
|
|
|
|
|
|
|
or INVALID_FUNCTION_SPECIFIED if the user provided an invalid |
612
|
|
|
|
|
|
|
function name |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
Usage: my $err_msg = get_error_message("read_xml_message"); |
615
|
|
|
|
|
|
|
=cut |
616
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
sub get_error_message { |
618
|
|
|
|
|
|
|
my $function = shift; |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
# check we got a function name |
621
|
|
|
|
|
|
|
if (!defined($function)) { |
622
|
|
|
|
|
|
|
return UNDEFINED_ARGUMENT_MSG; |
623
|
|
|
|
|
|
|
} |
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
return $error_msg{$function} if defined($error_msg{$function}); |
626
|
|
|
|
|
|
|
return INVALID_FUNCTION_SPECIFIED_MSG."$function"; |
627
|
|
|
|
|
|
|
} |
628
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
=head2 get_error_msg |
630
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
Shorthand call for get_error_message |
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
=cut |
634
|
|
|
|
|
|
|
sub get_error_msg{ |
635
|
|
|
|
|
|
|
my $fname = shift; |
636
|
|
|
|
|
|
|
return get_error_message($fname); |
637
|
|
|
|
|
|
|
} |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
########################## END EXPORTED FUNCTIONS ############################# |
641
|
|
|
|
|
|
|
########################## BEGIN UNEXPORTED FUNCTIONS ######################### |
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
# file_check |
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
#This function checks whether or not the currently-open file exists |
646
|
|
|
|
|
|
|
#Input: A filename to check |
647
|
|
|
|
|
|
|
#Output: 1 if the file exists, 0 otherwise |
648
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
sub file_check{ |
650
|
|
|
|
|
|
|
my $file = shift; |
651
|
|
|
|
|
|
|
my $fname = "file_check"; |
652
|
|
|
|
|
|
|
if( !defined($file) ){ |
653
|
|
|
|
|
|
|
$error_code{$fname} = UNDEFINED_ARGUMENT_CODE; |
654
|
|
|
|
|
|
|
$error_msg{$fname} = UNDEFINED_ARGUMENT_MSG; |
655
|
|
|
|
|
|
|
return 0; |
656
|
|
|
|
|
|
|
} |
657
|
|
|
|
|
|
|
if( -e $file ){ |
658
|
|
|
|
|
|
|
return 1; |
659
|
|
|
|
|
|
|
} |
660
|
|
|
|
|
|
|
else{ |
661
|
|
|
|
|
|
|
$error_code{$fname} = NO_SUCH_FILE_CODE; |
662
|
|
|
|
|
|
|
$error_msg{$fname} = NO_SUCH_FILE_MSG; |
663
|
|
|
|
|
|
|
return 0; |
664
|
|
|
|
|
|
|
} |
665
|
|
|
|
|
|
|
} |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
# decompress_file |
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
#This function decompresses a file using Perl's IO::Uncompress library. |
670
|
|
|
|
|
|
|
#Currently supports gzip, bzip2, RFC 1950/1951, zip,lzop,lzf,lzma,xz |
671
|
|
|
|
|
|
|
#Input: The filename to uncompress |
672
|
|
|
|
|
|
|
#Returns: undef on failure, the name of the uncompressed file on success |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
sub decompress_file{ |
675
|
|
|
|
|
|
|
my $file = shift; |
676
|
|
|
|
|
|
|
my $fname = "decompress_file"; |
677
|
|
|
|
|
|
|
if( !defined($file) ){ |
678
|
|
|
|
|
|
|
$error_code{$fname} = UNDEFINED_ARGUMENT_CODE; |
679
|
|
|
|
|
|
|
$error_msg{$fname} = UNDEFINED_ARGUMENT_MSG; |
680
|
|
|
|
|
|
|
return undef; |
681
|
|
|
|
|
|
|
} |
682
|
|
|
|
|
|
|
if( is_connected() ){ |
683
|
|
|
|
|
|
|
$error_code{$fname} = ALREADY_CONNECTED_CODE; |
684
|
|
|
|
|
|
|
$error_msg{$fname} = ALREADY_CONNECTED_MSG; |
685
|
|
|
|
|
|
|
return undef; |
686
|
|
|
|
|
|
|
} |
687
|
|
|
|
|
|
|
if( !file_check($file) || !file_check($scratch_dir) ){ |
688
|
|
|
|
|
|
|
$error_code{$fname} = NO_SUCH_FILE_CODE; |
689
|
|
|
|
|
|
|
$error_msg{$fname} = NO_SUCH_FILE_MSG; |
690
|
|
|
|
|
|
|
return undef; |
691
|
|
|
|
|
|
|
} |
692
|
|
|
|
|
|
|
unless( anyuncompress $file => "$scratch_dir/$output_file" ){ |
693
|
|
|
|
|
|
|
$error_code{$fname} = DECOMPRESS_FAIL_CODE; |
694
|
|
|
|
|
|
|
$error_msg{$fname} = DECOMPRESS_FAIL_MSG.": $@"; |
695
|
|
|
|
|
|
|
return undef; |
696
|
|
|
|
|
|
|
} |
697
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
return $output_file; |
699
|
|
|
|
|
|
|
} |
700
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
########################## END UNEXPORTED ##################################### |
702
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
=head1 ERROR CODES AND MESSAGES |
704
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
The following error codes and messages are defined: |
706
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
0: No Error |
708
|
|
|
|
|
|
|
'No Error' |
709
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
301: An argument to a function was undefined |
711
|
|
|
|
|
|
|
'Undefined Argument(s)' |
712
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
302: There is no active connection to a file |
714
|
|
|
|
|
|
|
'Not connected to a file' |
715
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
303: There is a currently-active connection to a file |
717
|
|
|
|
|
|
|
'Already connected to a file' |
718
|
|
|
|
|
|
|
|
719
|
|
|
|
|
|
|
304: The filename or directory given does not exist |
720
|
|
|
|
|
|
|
'Specified file/directory does not exist' |
721
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
305: A system call failed |
723
|
|
|
|
|
|
|
'System call failed' |
724
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
306: Decompressing the file failed |
726
|
|
|
|
|
|
|
'Failed to decompress file' |
727
|
|
|
|
|
|
|
|
728
|
|
|
|
|
|
|
307: The file was not opened successfully |
729
|
|
|
|
|
|
|
'Failed to open file' |
730
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
308: Initializing the XML Reader failed |
732
|
|
|
|
|
|
|
'Failed to initialize XML Reader' |
733
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
309: The XML Reader encountered a fatal error |
735
|
|
|
|
|
|
|
'XML Parser Error' |
736
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
310: The XML file passed in did not begin with an tag |
738
|
|
|
|
|
|
|
'File must begin with tag' |
739
|
|
|
|
|
|
|
|
740
|
|
|
|
|
|
|
311: An invalid function name was passed to get_error_[code/message/msg] |
741
|
|
|
|
|
|
|
'Invalid function specified' |
742
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
312: There was an error initializing one or more of the options to init_bgpdata |
744
|
|
|
|
|
|
|
'Failed to initialize file connection' |
745
|
|
|
|
|
|
|
|
746
|
|
|
|
|
|
|
313: At least one of the beginning ARCHIVER/OPENING or ARCHIVER/CLOSE |
747
|
|
|
|
|
|
|
messages were missing from the file |
748
|
|
|
|
|
|
|
NOTE: Setting the ignore_data_errors flag will suppress this |
749
|
|
|
|
|
|
|
'File is missing expected ARCHIVER messages' |
750
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
314: An additional ARCHIVER/OPENING message was encountered during file |
752
|
|
|
|
|
|
|
processing. This indicates a likely gap in the data. |
753
|
|
|
|
|
|
|
NOTE: Setting the ignore_incomplete_data flag will suppress this |
754
|
|
|
|
|
|
|
'File may be missing data' |
755
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
315: User tried to ignore all data errors, but was checking for incomplete data |
757
|
|
|
|
|
|
|
'Cannot have ignore_incomplete_data off with ignore_data_errors on' |
758
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
=head1 AUTHOR |
760
|
|
|
|
|
|
|
|
761
|
|
|
|
|
|
|
Jason Bartlett, C<< >> |
762
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
=head1 BUGS |
764
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
Please report any bugs or feature requests to |
766
|
|
|
|
|
|
|
C, or through |
767
|
|
|
|
|
|
|
the web interface at L. |
768
|
|
|
|
|
|
|
|
769
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
=head1 SUPPORT |
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
773
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
perldoc BGPmon::Fetch::File |
775
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
=cut |
777
|
|
|
|
|
|
|
|
778
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
779
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
Copyright (c) 2012 Colorado State University |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person |
783
|
|
|
|
|
|
|
obtaining a copy of this software and associated documentation |
784
|
|
|
|
|
|
|
files (the "Software"), to deal in the Software without |
785
|
|
|
|
|
|
|
restriction, including without limitation the rights to use, |
786
|
|
|
|
|
|
|
copy, modify, merge, publish, distribute, sublicense, and/or |
787
|
|
|
|
|
|
|
sell copies of the Software, and to permit persons to whom |
788
|
|
|
|
|
|
|
the Software is furnished to do so, subject to the following |
789
|
|
|
|
|
|
|
conditions: |
790
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be |
792
|
|
|
|
|
|
|
included in all copies or substantial portions of the Software. |
793
|
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
795
|
|
|
|
|
|
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
796
|
|
|
|
|
|
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
797
|
|
|
|
|
|
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
798
|
|
|
|
|
|
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
799
|
|
|
|
|
|
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
800
|
|
|
|
|
|
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
801
|
|
|
|
|
|
|
OTHER DEALINGS IN THE SOFTWARE.\ |
802
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
File: File.pm |
804
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
Authors: Jason Bartlett, Kaustubh Gadkari, Dan Massey, Cathie Olschanowsky |
806
|
|
|
|
|
|
|
Date: 13 October 2013 |
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
=cut |
809
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
1; # End of BGPmon::Fetch::File |