| Filename | /home/ocbnet/domain/ocbnet.ch/vhost/webmerge/htdocs/webmerge/scripts/modules/RTP/Webmerge/IO.pm | 
| Statements | Executed 62863 statements in 7.25s | 
| Calls | P | F | Exclusive Time | Inclusive Time | Subroutine | 
|---|---|---|---|---|---|
| 1542 | 1 | 1 | 3.72s | 3.72s | RTP::Webmerge::IO::CORE:syswrite (opcode) | 
| 39 | 3 | 3 | 1.87s | 5.70s | RTP::Webmerge::IO::writefile | 
| 2618 | 6 | 4 | 842ms | 4.53s | RTP::Webmerge::IO::readfile | 
| 2653 | 2 | 1 | 360ms | 391ms | RTP::Webmerge::IO::lock_file | 
| 2614 | 1 | 1 | 200ms | 200ms | RTP::Webmerge::IO::CORE:sysopen (opcode) | 
| 7158 | 1 | 1 | 77.3ms | 77.3ms | RTP::Webmerge::IO::CORE:sysread (opcode) | 
| 2614 | 1 | 1 | 64.0ms | 64.0ms | RTP::Webmerge::IO::CORE:close (opcode) | 
| 2653 | 2 | 1 | 42.8ms | 42.8ms | RTP::Webmerge::IO::CORE:ftis (opcode) | 
| 2692 | 2 | 1 | 31.5ms | 31.5ms | RTP::Webmerge::IO::CORE:flock (opcode) | 
| 2614 | 1 | 1 | 10.8ms | 10.8ms | RTP::Webmerge::IO::CORE:subst (opcode) | 
| 1 | 1 | 1 | 2.21ms | 17.7ms | RTP::Webmerge::IO::BEGIN@38 | 
| 39 | 1 | 1 | 1.05ms | 1.05ms | RTP::Webmerge::IO::CORE:ftdir (opcode) | 
| 1 | 1 | 1 | 85µs | 340µs | RTP::Webmerge::IO::BEGIN@8 | 
| 1 | 1 | 1 | 59µs | 310µs | RTP::Webmerge::IO::BEGIN@29 | 
| 1 | 1 | 1 | 58µs | 320µs | RTP::Webmerge::IO::BEGIN@32 | 
| 1 | 1 | 1 | 54µs | 87µs | RTP::Webmerge::IO::BEGIN@10 | 
| 1 | 1 | 1 | 53µs | 53µs | RTP::Webmerge::IO::BEGIN@18.12 | 
| 1 | 1 | 1 | 52µs | 385µs | RTP::Webmerge::IO::BEGIN@35 | 
| 1 | 1 | 1 | 50µs | 140µs | RTP::Webmerge::IO::BEGIN@9 | 
| 1 | 1 | 1 | 28µs | 28µs | RTP::Webmerge::IO::BEGIN@21 | 
| 1 | 1 | 1 | 26µs | 26µs | RTP::Webmerge::IO::BEGIN@24 | 
| 1 | 1 | 1 | 22µs | 22µs | RTP::Webmerge::IO::BEGIN@18 | 
| 1 | 1 | 1 | 22µs | 22µs | RTP::Webmerge::IO::BEGIN@15 | 
| 0 | 0 | 0 | 0s | 0s | RTP::Webmerge::IO::__ANON__[:66] | 
| 0 | 0 | 0 | 0s | 0s | RTP::Webmerge::IO::filelist | 
| 0 | 0 | 0 | 0s | 0s | RTP::Webmerge::IO::processfile | 
| Line | State ments | Time on line | Calls | Time in subs | Code | 
|---|---|---|---|---|---|
| 1 | ################################################################################################### | ||||
| 2 | # Copyright 2013 by Marcel Greter | ||||
| 3 | # This file is part of Webmerge (GPL3) | ||||
| 4 | ################################################################################################### | ||||
| 5 | package RTP::Webmerge::IO; | ||||
| 6 | ################################################################################################### | ||||
| 7 | |||||
| 8 | 2 | 157µs | 2 | 595µs | # spent 340µs (85+255) within RTP::Webmerge::IO::BEGIN@8 which was called:
#    once (85µs+255µs) by main::BEGIN@29 at line 8 # spent   340µs making 1 call to RTP::Webmerge::IO::BEGIN@8
# spent   255µs making 1 call to Exporter::import | 
| 9 | 2 | 145µs | 2 | 231µs | # spent 140µs (50+91) within RTP::Webmerge::IO::BEGIN@9 which was called:
#    once (50µs+91µs) by main::BEGIN@29 at line 9 # spent   140µs making 1 call to RTP::Webmerge::IO::BEGIN@9
# spent    91µs making 1 call to strict::import | 
| 10 | 2 | 193µs | 2 | 119µs | # spent 87µs (54+32) within RTP::Webmerge::IO::BEGIN@10 which was called:
#    once (54µs+32µs) by main::BEGIN@29 at line 10 # spent    87µs making 1 call to RTP::Webmerge::IO::BEGIN@10
# spent    32µs making 1 call to warnings::import | 
| 11 | |||||
| 12 | ################################################################################################### | ||||
| 13 | |||||
| 14 | # define our version string | ||||
| 15 | 1 | 145µs | 1 | 22µs | # spent 22µs within RTP::Webmerge::IO::BEGIN@15 which was called:
#    once (22µs+0s) by main::BEGIN@29 at line 15 # spent    22µs making 1 call to RTP::Webmerge::IO::BEGIN@15 | 
| 16 | |||||
| 17 | # load exporter and inherit from it | ||||
| 18 | 3 | 369µs | 2 | 75µs | BEGIN { use Exporter qw(); our @ISA = qw(Exporter) } # spent    53µs making 1 call to RTP::Webmerge::IO::BEGIN@18.12
# spent    22µs making 1 call to RTP::Webmerge::IO::BEGIN@18 | 
| 19 | |||||
| 20 | # define our functions to be exported | ||||
| 21 | 1 | 178µs | 1 | 28µs | # spent 28µs within RTP::Webmerge::IO::BEGIN@21 which was called:
#    once (28µs+0s) by main::BEGIN@29 at line 21 # spent    28µs making 1 call to RTP::Webmerge::IO::BEGIN@21 | 
| 22 | |||||
| 23 | # define our functions to be exported | ||||
| 24 | 1 | 148µs | 1 | 26µs | # spent 26µs within RTP::Webmerge::IO::BEGIN@24 which was called:
#    once (26µs+0s) by main::BEGIN@29 at line 24 # spent    26µs making 1 call to RTP::Webmerge::IO::BEGIN@24 | 
| 25 | |||||
| 26 | ################################################################################################### | ||||
| 27 | |||||
| 28 | # resolve filepath | ||||
| 29 | 2 | 165µs | 2 | 561µs | # spent 310µs (59+251) within RTP::Webmerge::IO::BEGIN@29 which was called:
#    once (59µs+251µs) by main::BEGIN@29 at line 29 # spent   310µs making 1 call to RTP::Webmerge::IO::BEGIN@29
# spent   251µs making 1 call to Exporter::import | 
| 30 | |||||
| 31 | # load webmerge core path module | ||||
| 32 | 2 | 171µs | 2 | 582µs | # spent 320µs (58+262) within RTP::Webmerge::IO::BEGIN@32 which was called:
#    once (58µs+262µs) by main::BEGIN@29 at line 32 # spent   320µs making 1 call to RTP::Webmerge::IO::BEGIN@32
# spent   262µs making 1 call to Exporter::import | 
| 33 | |||||
| 34 | # override core glob (case insensitive) | ||||
| 35 | 2 | 184µs | 2 | 717µs | # spent 385µs (52+332) within RTP::Webmerge::IO::BEGIN@35 which was called:
#    once (52µs+332µs) by main::BEGIN@29 at line 35 # spent   385µs making 1 call to RTP::Webmerge::IO::BEGIN@35
# spent   332µs making 1 call to File::Glob::import | 
| 36 | |||||
| 37 | # load flags for the system file operation calls | ||||
| 38 | 2 | 7.28ms | 2 | 20.2ms | # spent 17.7ms (2.21+15.4) within RTP::Webmerge::IO::BEGIN@38 which was called:
#    once (2.21ms+15.4ms) by main::BEGIN@29 at line 38 # spent  17.7ms making 1 call to RTP::Webmerge::IO::BEGIN@38
# spent  2.54ms making 1 call to Exporter::import | 
| 39 | |||||
| 40 | ################################################################################################### | ||||
| 41 | |||||
| 42 | # lock file exclusive | ||||
| 43 | # return false if lock could not be | ||||
| 44 | # aquired after the given timeout (in s) | ||||
| 45 | sub lock_file | ||||
| 46 | { | ||||
| 47 | |||||
| 48 | # get input variables | ||||
| 49 | 2653 | 13.7ms | my ($fh, $flag, $timeout) = @_; | ||
| 50 | |||||
| 51 | # simply lock with blocking when no timeout given | ||||
| 52 | 2653 | 3.80ms | return flock($fh, $flag) unless defined $timeout; | ||
| 53 | |||||
| 54 | # this is an alternative locking mechanism with timeout | ||||
| 55 | # it has the disadvantage that while we are waiting in the | ||||
| 56 | # select call another process might get the lock before us | ||||
| 57 | # my $time = time; while($time + $timeout > time) { | ||||
| 58 | # return 1 if(flock($fh, $lock | LOCK_NB)); | ||||
| 59 | # select(undef, undef, undef, $intervall) } | ||||
| 60 | |||||
| 61 | # eval in perl is a bit like try/catch | ||||
| 62 | eval | ||||
| 63 | 2653 | 13.3ms | { | ||
| 64 | |||||
| 65 | # die needs the "\n" to not append trace | ||||
| 66 | 2653 | 134ms | local $SIG{ALRM} = sub { die "alarm\n" }; | ||
| 67 | |||||
| 68 | # setup the alarm | ||||
| 69 | 2653 | 26.8ms | alarm $timeout; | ||
| 70 | |||||
| 71 | # try to lock the file | ||||
| 72 | 2653 | 74.0ms | 2653 | 31.1ms | flock($fh, $flag);                 # spent  31.1ms making 2653 calls to RTP::Webmerge::IO::CORE:flock, avg 12µs/call | 
| 73 | |||||
| 74 | # reset alarm | ||||
| 75 | 2653 | 81.0ms | alarm 0; | ||
| 76 | |||||
| 77 | }; | ||||
| 78 | |||||
| 79 | # there was an error | ||||
| 80 | 2653 | 2.54ms | if ($@) | ||
| 81 | { | ||||
| 82 | |||||
| 83 | # propagate unexpected errors | ||||
| 84 | die unless $@ eq "alarm\n"; | ||||
| 85 | |||||
| 86 | # return failure | ||||
| 87 | return 0; | ||||
| 88 | |||||
| 89 | } | ||||
| 90 | |||||
| 91 | # return success | ||||
| 92 | 2653 | 49.0ms | return 1; | ||
| 93 | |||||
| 94 | } | ||||
| 95 | # EO lock_file | ||||
| 96 | |||||
| 97 | ################################################################################################### | ||||
| 98 | |||||
| 99 | # read file and return data (flocked) | ||||
| 100 | sub readfile ($;$$) | ||||
| 101 | # spent 4.53s (842ms+3.69) within RTP::Webmerge::IO::readfile which was called 2618 times, avg 1.73ms/call:
# 2560 times (732ms+3.60s) by RTP::Webmerge::Process::CSS::Inlinedata::inline_url at line 273 of webmerge/scripts/modules/RTP/Webmerge/Process/CSS/Inlinedata.pm, avg 1.69ms/call
#   20 times (43.7ms+29.5ms) by RTP::Webmerge::IO::CSS::incCSS at line 80 of webmerge/scripts/modules/RTP/Webmerge/IO/CSS.pm, avg 3.66ms/call
#   18 times (61.9ms+35.8ms) by RTP::Webmerge::Checksum::crcCheckEntry at line 80 of webmerge/scripts/modules/RTP/Webmerge/Checksum.pm, avg 5.43ms/call
#   18 times (4.21ms+23.6ms) by RTP::Webmerge::Checksum::crcCheckEntry at line 70 of webmerge/scripts/modules/RTP/Webmerge/Checksum.pm, avg 1.54ms/call
#       once (372µs+1.24ms) by main::read_xml at line 310 of webmerge/scripts/webmerge.pl
#       once (206µs+939µs) by main::get_xml at line 283 of webmerge/scripts/webmerge.pl | ||||
| 102 | |||||
| 103 | # get input variables | ||||
| 104 | 2618 | 16.5ms | my ($file, $atomic, $binary) = @_; | ||
| 105 | |||||
| 106 | # check if file has already beed written | ||||
| 107 | 2618 | 15.8ms | if ($atomic && exists $atomic->{$file}) | ||
| 108 | { return $atomic->{$file}->[0]; } | ||||
| 109 | |||||
| 110 | # check if file does exist | ||||
| 111 | # check_path may bail otherwise | ||||
| 112 | 2614 | 151ms | 5228 | 2.83s | if (-e $file)         # spent  2.79s making 2614 calls to RTP::Webmerge::Path::check_path, avg 1.07ms/call
        # spent  41.4ms making 2614 calls to RTP::Webmerge::IO::CORE:ftis, avg 16µs/call | 
| 113 | { | ||||
| 114 | |||||
| 115 | # resolve path and make absolute | ||||
| 116 | $file = check_path($file) || $file; | ||||
| 117 | |||||
| 118 | } else { | ||||
| 119 | |||||
| 120 | # parse into filename and path | ||||
| 121 | # the path must exists at this point | ||||
| 122 | my ($name, $path) = fileparse($file); | ||||
| 123 | |||||
| 124 | # resolve path and make absolute | ||||
| 125 | $path = check_path($path) || $path; | ||||
| 126 | |||||
| 127 | # re-join the complete file uri | ||||
| 128 | $file = join('/', $path, $name); | ||||
| 129 | |||||
| 130 | } | ||||
| 131 | |||||
| 132 | # check if file has already beed written | ||||
| 133 | 2614 | 20.1ms | if ($atomic && exists $atomic->{$file}) | ||
| 134 | { return $atomic->{$file}->[0]; } | ||||
| 135 | |||||
| 136 | # declare local variables | ||||
| 137 | 2614 | 12.0ms | my $rv, my $data = ''; | ||
| 138 | |||||
| 139 | # open the file | ||||
| 140 | 2614 | 280ms | 2614 | 200ms | croak "could not open $file: $!" unless sysopen(my $fh, $file, O_RDWR);         # spent   200ms making 2614 calls to RTP::Webmerge::IO::CORE:sysopen, avg 76µs/call | 
| 141 | |||||
| 142 | # aquire exclusive lock on the file (will block) | ||||
| 143 | 2614 | 41.1ms | 2614 | 385ms | croak "could not lock $file: $!" unless lock_file($fh, LOCK_EX, 4);         # spent   385ms making 2614 calls to RTP::Webmerge::IO::lock_file, avg 147µs/call | 
| 144 | |||||
| 145 | # use binmode | ||||
| 146 | 2614 | 39.3ms | 2614 | 120ms | $fh->binmode;         # spent   120ms making 2614 calls to IO::File::binmode, avg 46µs/call | 
| 147 | |||||
| 148 | # read the whole file buffer by buffer | ||||
| 149 | 2614 | 324ms | 7158 | 77.3ms | while($rv = sysread($fh, my $buffer, 4096)) { $data .= $buffer; }         # spent  77.3ms making 7158 calls to RTP::Webmerge::IO::CORE:sysread, avg 11µs/call | 
| 150 | |||||
| 151 | # check for error conditions | ||||
| 152 | 2614 | 3.42ms | croak "read error: $!" unless defined $rv; | ||
| 153 | 2614 | 3.20ms | croak "unknown read error: $!" unless $rv == 0; | ||
| 154 | |||||
| 155 | # close the file (this should probably never error) | ||||
| 156 | 2614 | 127ms | 2614 | 64.0ms | croak "could not close input file: $!" unless close $fh;         # spent  64.0ms making 2614 calls to RTP::Webmerge::IO::CORE:close, avg 24µs/call | 
| 157 | |||||
| 158 | # remove unwanted utf8 boms | ||||
| 159 | # this must not be protected | ||||
| 160 | # we seldomly use the data again | ||||
| 161 | # if it is not a text type | ||||
| 162 | 2614 | 108ms | 2614 | 10.8ms | $data =~ s/^\xEF\xBB\xBF// unless $binary;         # spent  10.8ms making 2614 calls to RTP::Webmerge::IO::CORE:subst, avg 4µs/call | 
| 163 | |||||
| 164 | # return a data ref | ||||
| 165 | # this will safe memory | ||||
| 166 | 2614 | 103ms | return \$data | ||
| 167 | |||||
| 168 | } | ||||
| 169 | # EO sub readfile | ||||
| 170 | |||||
| 171 | ################################################################################################### | ||||
| 172 | |||||
| 173 | # write data to a file (flocked) | ||||
| 174 | sub writefile ($$;$$) | ||||
| 175 | # spent 5.70s (1.87+3.82) within RTP::Webmerge::IO::writefile which was called 39 times, avg 146ms/call:
# 18 times (1.86s+3.77s) by RTP::Webmerge::IO::CSS::writeCSS at line 171 of webmerge/scripts/modules/RTP/Webmerge/IO/CSS.pm, avg 313ms/call
# 18 times (5.75ms+44.6ms) by RTP::Webmerge::Merge::writer at line 151 of webmerge/scripts/modules/RTP/Webmerge/Merge.pm, avg 2.80ms/call
#  3 times (3.77ms+14.1ms) by RTP::Webmerge::Process::CSS::Spritesets::__ANON__[/home/ocbnet/domain/ocbnet.ch/vhost/webmerge/htdocs/webmerge/scripts/modules/RTP/Webmerge/Process/CSS/Spritesets.pm:98] at line 88 of webmerge/scripts/modules/RTP/Webmerge/Process/CSS/Spritesets.pm, avg 5.97ms/call | ||||
| 176 | |||||
| 177 | 39 | 43µs | my $fh; | ||
| 178 | |||||
| 179 | # get input variables | ||||
| 180 | 39 | 334µs | my ($file, $out, $atomic, $binary) = @_; | ||
| 181 | |||||
| 182 | # check if file does exist | ||||
| 183 | # check_path may bail otherwise | ||||
| 184 | 39 | 2.85ms | 78 | 41.0ms | if (-e $file)         # spent  39.6ms making 39 calls to RTP::Webmerge::Path::check_path, avg 1.01ms/call
        # spent  1.40ms making 39 calls to RTP::Webmerge::IO::CORE:ftis, avg 36µs/call | 
| 185 | { | ||||
| 186 | |||||
| 187 | # resolve path and make absolute | ||||
| 188 | $file = check_path($file) || $file; | ||||
| 189 | |||||
| 190 | } else { | ||||
| 191 | |||||
| 192 | # parse into filename and path | ||||
| 193 | # the path must exists at this point | ||||
| 194 | my ($name, $path) = fileparse($file); | ||||
| 195 | |||||
| 196 | # resolve path and make absolute | ||||
| 197 | $path = check_path($path) || $path; | ||||
| 198 | |||||
| 199 | # re-join the complete file uri | ||||
| 200 | $file = join('/', $path, $name); | ||||
| 201 | |||||
| 202 | } | ||||
| 203 | |||||
| 204 | # declare local variables | ||||
| 205 | 39 | 94µs | my $rv = undef; | ||
| 206 | |||||
| 207 | # create a memory copy of content | ||||
| 208 | 39 | 7.76ms | my $data = \(my $foo = ${$out}); | ||
| 209 | |||||
| 210 | # convert from mac/win newlines to unix newlines | ||||
| 211 | # ${$data} =~ s/(?:\r\n|\n\r)/\n/gm unless $binary; | ||||
| 212 | |||||
| 213 | # open the file via atomic interface | ||||
| 214 | # my $fh = RTP::IO::AtomicFile->open($file, 'w'); | ||||
| 215 | |||||
| 216 | 39 | 785µs | 39 | 13.4ms | my $dir = dirname $file;         # spent  13.4ms making 39 calls to File::Basename::dirname, avg 344µs/call | 
| 217 | |||||
| 218 | 39 | 1.61ms | 39 | 1.05ms | die "directory does not exist: ", $dir unless -d $dir;         # spent  1.05ms making 39 calls to RTP::Webmerge::IO::CORE:ftdir, avg 27µs/call | 
| 219 | |||||
| 220 | # looks like we already written this file | ||||
| 221 | # truncate, sync and unlock, then write again | ||||
| 222 | 39 | 550µs | if (exists $atomic->{$file}) | ||
| 223 | { | ||||
| 224 | |||||
| 225 | # get the stored old handle | ||||
| 226 | $fh = $atomic->{$file}->[1]; | ||||
| 227 | # enable autoflush | ||||
| 228 | # $fh->autoflush(1); | ||||
| 229 | # set the position to start | ||||
| 230 | $fh->seek(0, SEEK_SET); | ||||
| 231 | $fh->sysseek(0, SEEK_SET); | ||||
| 232 | # make the file empty | ||||
| 233 | $fh->truncate(0); | ||||
| 234 | # write out changes | ||||
| 235 | $fh->flush; | ||||
| 236 | # release file locks | ||||
| 237 | flock($fh, LOCK_UN); | ||||
| 238 | } | ||||
| 239 | else | ||||
| 240 | { | ||||
| 241 | # open the file via atomic interface | ||||
| 242 | 39 | 1.35ms | 39 | 11.7ms | $fh = RTP::IO::AtomicFile->new;                 # spent  11.7ms making 39 calls to RTP::IO::AtomicFile::new, avg 300µs/call | 
| 243 | # append another suffix as some optimizers | ||||
| 244 | # already use the same, be on the save side | ||||
| 245 | 39 | 180µs | ${*$fh}{'io_atomicfile_suffix'} = '.webmerge'; | ||
| 246 | # open the file via atomic interface | ||||
| 247 | 39 | 618µs | 39 | 24.2ms | $fh->open($file, 'w');                 # spent  24.2ms making 39 calls to RTP::IO::AtomicFile::open, avg 620µs/call | 
| 248 | } | ||||
| 249 | |||||
| 250 | 39 | 107µs | die "could not open file: $file: $!" unless defined $fh; | ||
| 251 | |||||
| 252 | # use binmode | ||||
| 253 | 39 | 772µs | 39 | 1.74ms | $fh->binmode;         # spent  1.74ms making 39 calls to IO::File::binmode, avg 45µs/call | 
| 254 | |||||
| 255 | # error out if there was an error opening the file | ||||
| 256 | 39 | 59µs | croak "could not open $file: $!" unless $fh; | ||
| 257 | |||||
| 258 | # aquire exclusive lock on the file (will block) | ||||
| 259 | 39 | 563µs | 39 | 6.07ms | croak "could not lock $file: $!" unless lock_file($fh, LOCK_EX, 4);         # spent  6.07ms making 39 calls to RTP::Webmerge::IO::lock_file, avg 156µs/call | 
| 260 | |||||
| 261 | # $file = ${*$fh}{'io_atomicfile_temp'} if ${*$fh}{'io_atomicfile_temp'}; | ||||
| 262 | |||||
| 263 | # only store if atomic is given | ||||
| 264 | 39 | 647µs | $atomic->{$file} = [$out, $fh] if $atomic; | ||
| 265 | |||||
| 266 | 39 | 780µs | if (defined(my $temp = ${*$fh}{'io_atomicfile_temp'})) | ||
| 267 | { | ||||
| 268 | # only store if atomic is given | ||||
| 269 | $atomic->{$temp} = [$out, $fh] if $atomic; | ||||
| 270 | } | ||||
| 271 | |||||
| 272 | # write the whole file buffer by buffer | ||||
| 273 | 1542 | 5.58s | 1542 | 3.72s | while($rv = syswrite($fh, ${$data}, 4096)) { substr(${$data}, 0, $rv, ''); }         # spent  3.72s making 1542 calls to RTP::Webmerge::IO::CORE:syswrite, avg 2.42ms/call | 
| 274 | |||||
| 275 | # check for error conditions | ||||
| 276 | 39 | 85µs | croak "write error: $!" unless defined $rv; | ||
| 277 | 39 | 55µs | croak "unknown write error: $!" unless $rv == 0; | ||
| 278 | |||||
| 279 | 39 | 951µs | 39 | 398µs | flock($fh, LOCK_UN);         # spent   398µs making 39 calls to RTP::Webmerge::IO::CORE:flock, avg 10µs/call | 
| 280 | |||||
| 281 | # return file handle | ||||
| 282 | # store to block file | ||||
| 283 | 39 | 1.13ms | return $fh | ||
| 284 | |||||
| 285 | } | ||||
| 286 | # EO sub writefile | ||||
| 287 | |||||
| 288 | |||||
| 289 | ################################################################################################### | ||||
| 290 | |||||
| 291 | # process a file on disk | ||||
| 292 | # it does open the file first | ||||
| 293 | # aquires an exclusive lock | ||||
| 294 | # then reads the whole file | ||||
| 295 | # call the processor on the data | ||||
| 296 | # then write back the new data | ||||
| 297 | # flush, close und release lock | ||||
| 298 | sub processfile | ||||
| 299 | { | ||||
| 300 | |||||
| 301 | # get input variables | ||||
| 302 | my ($file, $processor, $config, $options) = @_; | ||||
| 303 | |||||
| 304 | # resolve path | ||||
| 305 | $file = check_path($file); | ||||
| 306 | |||||
| 307 | # declare local variables | ||||
| 308 | my $rv, my $data = ''; | ||||
| 309 | |||||
| 310 | # open the file in read write mode | ||||
| 311 | croak "could not open $file: $!" unless sysopen(my $fh, $file, O_RDWR); | ||||
| 312 | |||||
| 313 | # put all file into binary mode for eol handling | ||||
| 314 | croak "could not binmode $file: $!" unless binmode($fh); | ||||
| 315 | |||||
| 316 | # aquire exclusive lock on the file (will block) | ||||
| 317 | croak "could not lock $file: $!" unless lock_file($fh, LOCK_EX, 1000); | ||||
| 318 | |||||
| 319 | # read the whole file buffer by buffer | ||||
| 320 | while($rv = sysread($fh, my $buffer, 4096)) { $data .= $buffer; } | ||||
| 321 | |||||
| 322 | # check for read error conditions | ||||
| 323 | croak "read error: $!" unless defined $rv; | ||||
| 324 | croak "unknown read error: $!" unless $rv == 0; | ||||
| 325 | |||||
| 326 | # call the processor to change the content | ||||
| 327 | unless (&{$processor}(\$data, $config, $options)) | ||||
| 328 | { croak "could not process content: $!"; } | ||||
| 329 | |||||
| 330 | # seek to the file begining after processing is done | ||||
| 331 | croak "could not seek $file: $!" unless sysseek($fh, 0, SEEK_SET); | ||||
| 332 | |||||
| 333 | # then truncate the file to zero size (make it empty) | ||||
| 334 | croak "could not truncate $file: $!" unless truncate($fh, 0); | ||||
| 335 | |||||
| 336 | # then write the complete content again to the file | ||||
| 337 | croak "could not write to $file: $!" unless print $fh $data; | ||||
| 338 | |||||
| 339 | # close the file (this should probably never error) | ||||
| 340 | croak "could not close file: $!" unless close $fh; | ||||
| 341 | |||||
| 342 | } | ||||
| 343 | # EO sub processfile | ||||
| 344 | |||||
| 345 | ################################################################################################### | ||||
| 346 | |||||
| 347 | # get a list of files from a directory | ||||
| 348 | sub filelist | ||||
| 349 | { | ||||
| 350 | |||||
| 351 | # get input variables | ||||
| 352 | my ($root, $file, $recursive) = @_; | ||||
| 353 | |||||
| 354 | # resolve path | ||||
| 355 | $root = check_path($root); | ||||
| 356 | |||||
| 357 | # declare local variables | ||||
| 358 | my @dirs = ($root), my @files; | ||||
| 359 | |||||
| 360 | while(defined(my $root = shift(@dirs))) | ||||
| 361 | { | ||||
| 362 | |||||
| 363 | # use glob function to match the files | ||||
| 364 | # could implement my own regex match, but | ||||
| 365 | # glob is much simpler and securer to use | ||||
| 366 | push(@files, bsd_glob(join('/', $root, $file))); | ||||
| 367 | |||||
| 368 | # open the directory to read all entries | ||||
| 369 | opendir(my $dh, $root) or die "could not opendir $root: $!"; | ||||
| 370 | |||||
| 371 | # read all entries in this directory | ||||
| 372 | foreach my $entry (readdir($dh)) | ||||
| 373 | { | ||||
| 374 | |||||
| 375 | # dont handle directory pointers | ||||
| 376 | next if $entry eq '.' || $entry eq '..'; | ||||
| 377 | |||||
| 378 | # create the complete file path | ||||
| 379 | my $path = join('/', $root, $entry); | ||||
| 380 | |||||
| 381 | # add directory to processings if recursive | ||||
| 382 | push(@dirs, $path) if -d $path && $recursive; | ||||
| 383 | |||||
| 384 | } | ||||
| 385 | # EO each readdir | ||||
| 386 | |||||
| 387 | # close directory | ||||
| 388 | closedir($dh); | ||||
| 389 | |||||
| 390 | } | ||||
| 391 | # EO while readdir | ||||
| 392 | |||||
| 393 | # return array ref | ||||
| 394 | return \ @files; | ||||
| 395 | |||||
| 396 | } | ||||
| 397 | # EO sub filelist | ||||
| 398 | |||||
| 399 | ################################################################################################### | ||||
| 400 | ################################################################################################### | ||||
| 401 | 1 | 13µs | 1; | ||
| # spent 64.0ms within RTP::Webmerge::IO::CORE:close which was called 2614 times, avg 24µs/call:
# 2614 times (64.0ms+0s) by RTP::Webmerge::IO::readfile at line 156, avg 24µs/call | |||||
| sub RTP::Webmerge::IO::CORE:flock; # opcode | |||||
| # spent 1.05ms within RTP::Webmerge::IO::CORE:ftdir which was called 39 times, avg 27µs/call:
# 39 times (1.05ms+0s) by RTP::Webmerge::IO::writefile at line 218, avg 27µs/call | |||||
| sub RTP::Webmerge::IO::CORE:ftis; # opcode | |||||
| # spent 10.8ms within RTP::Webmerge::IO::CORE:subst which was called 2614 times, avg 4µs/call:
# 2614 times (10.8ms+0s) by RTP::Webmerge::IO::readfile at line 162, avg 4µs/call | |||||
| # spent 200ms within RTP::Webmerge::IO::CORE:sysopen which was called 2614 times, avg 76µs/call:
# 2614 times (200ms+0s) by RTP::Webmerge::IO::readfile at line 140, avg 76µs/call | |||||
| # spent 77.3ms within RTP::Webmerge::IO::CORE:sysread which was called 7158 times, avg 11µs/call:
# 7158 times (77.3ms+0s) by RTP::Webmerge::IO::readfile at line 149, avg 11µs/call | |||||
| # spent 3.72s within RTP::Webmerge::IO::CORE:syswrite which was called 1542 times, avg 2.42ms/call:
# 1542 times (3.72s+0s) by RTP::Webmerge::IO::writefile at line 273, avg 2.42ms/call |