Filename | /cygdrive/c/lo/libo-master/instsetoo_native/util/C:/lo/libo-master/solenv/bin/modules/installer/windows/update.pm |
Statements | Executed 87 statements in 5.29ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 393µs | 396µs | BEGIN@30 | installer::windows::update::
1 | 1 | 1 | 143µs | 197µs | get_databasename_from_list | installer::windows::update::
1 | 1 | 1 | 58µs | 697µs | readdatabase | installer::windows::update::
27 | 2 | 1 | 53µs | 53µs | CORE:match (opcode) | installer::windows::update::
1 | 1 | 1 | 16µs | 18µs | BEGIN@31 | installer::windows::update::
1 | 1 | 1 | 15µs | 16µs | BEGIN@33 | installer::windows::update::
1 | 1 | 1 | 15µs | 17µs | BEGIN@34 | installer::windows::update::
1 | 1 | 1 | 14µs | 16µs | BEGIN@32 | installer::windows::update::
1 | 1 | 1 | 14µs | 16µs | BEGIN@35 | installer::windows::update::
0 | 0 | 0 | 0s | 0s | analyze_idt_file | installer::windows::update::
0 | 0 | 0 | 0s | 0s | collect_all_keys | installer::windows::update::
0 | 0 | 0 | 0s | 0s | correct_database | installer::windows::update::
0 | 0 | 0 | 0s | 0s | create_database_hashes | installer::windows::update::
0 | 0 | 0 | 0s | 0s | extract_all_tables_from_msidatabase | installer::windows::update::
0 | 0 | 0 | 0s | 0s | get_oneline_hash | installer::windows::update::
0 | 0 | 0 | 0s | 0s | read_all_tables_from_msidatabase | installer::windows::update::
0 | 0 | 0 | 0s | 0s | readmergedatabase | installer::windows::update::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | #************************************************************************* | ||||
2 | # | ||||
3 | # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||||
4 | # | ||||
5 | # Copyright 2000, 2010 Oracle and/or its affiliates. | ||||
6 | # | ||||
7 | # OpenOffice.org - a multi-platform office productivity suite | ||||
8 | # | ||||
9 | # This file is part of OpenOffice.org. | ||||
10 | # | ||||
11 | # OpenOffice.org is free software: you can redistribute it and/or modify | ||||
12 | # it under the terms of the GNU Lesser General Public License version 3 | ||||
13 | # only, as published by the Free Software Foundation. | ||||
14 | # | ||||
15 | # OpenOffice.org is distributed in the hope that it will be useful, | ||||
16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
18 | # GNU Lesser General Public License version 3 for more details | ||||
19 | # (a copy is included in the LICENSE file that accompanied this code). | ||||
20 | # | ||||
21 | # You should have received a copy of the GNU Lesser General Public License | ||||
22 | # version 3 along with OpenOffice.org. If not, see | ||||
23 | # <http://www.openoffice.org/license.html> | ||||
24 | # for a copy of the LGPLv3 License. | ||||
25 | # | ||||
26 | #************************************************************************* | ||||
27 | |||||
28 | package installer::windows::update; | ||||
29 | |||||
30 | 2 | 67µs | 2 | 400µs | # spent 396µs (393+4) within installer::windows::update::BEGIN@30 which was called:
# once (393µs+4µs) by installer::windows::msp::BEGIN@41 at line 30 # spent 396µs making 1 call to installer::windows::update::BEGIN@30
# spent 4µs making 1 call to UNIVERSAL::import |
31 | 2 | 56µs | 2 | 21µs | # spent 18µs (16+3) within installer::windows::update::BEGIN@31 which was called:
# once (16µs+3µs) by installer::windows::msp::BEGIN@41 at line 31 # spent 18µs making 1 call to installer::windows::update::BEGIN@31
# spent 2µs making 1 call to UNIVERSAL::import |
32 | 2 | 54µs | 2 | 18µs | # spent 16µs (14+2) within installer::windows::update::BEGIN@32 which was called:
# once (14µs+2µs) by installer::windows::msp::BEGIN@41 at line 32 # spent 16µs making 1 call to installer::windows::update::BEGIN@32
# spent 2µs making 1 call to UNIVERSAL::import |
33 | 2 | 54µs | 2 | 18µs | # spent 16µs (15+2) within installer::windows::update::BEGIN@33 which was called:
# once (15µs+2µs) by installer::windows::msp::BEGIN@41 at line 33 # spent 16µs making 1 call to installer::windows::update::BEGIN@33
# spent 2µs making 1 call to UNIVERSAL::import |
34 | 2 | 52µs | 2 | 19µs | # spent 17µs (15+2) within installer::windows::update::BEGIN@34 which was called:
# once (15µs+2µs) by installer::windows::msp::BEGIN@41 at line 34 # spent 17µs making 1 call to installer::windows::update::BEGIN@34
# spent 2µs making 1 call to UNIVERSAL::import |
35 | 2 | 4.76ms | 2 | 18µs | # spent 16µs (14+2) within installer::windows::update::BEGIN@35 which was called:
# once (14µs+2µs) by installer::windows::msp::BEGIN@41 at line 35 # spent 16µs making 1 call to installer::windows::update::BEGIN@35
# spent 2µs making 1 call to UNIVERSAL::import |
36 | |||||
37 | ################################################################################# | ||||
38 | # Extracting all tables from an msi database | ||||
39 | ################################################################################# | ||||
40 | |||||
41 | sub extract_all_tables_from_msidatabase | ||||
42 | { | ||||
43 | my ($fulldatabasepath, $workdir) = @_; | ||||
44 | |||||
45 | my $msidb = "msidb.exe"; # Has to be in the path | ||||
46 | my $infoline = ""; | ||||
47 | my $systemcall = ""; | ||||
48 | my $returnvalue = ""; | ||||
49 | my $extraslash = ""; # Has to be set for non-ActiveState perl | ||||
50 | |||||
51 | # Export of all tables by using "*" | ||||
52 | |||||
53 | if ( $^O =~ /cygwin/i ) { | ||||
54 | # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) | ||||
55 | $fulldatabasepath =~ s/\//\\\\/g; | ||||
56 | $workdir =~ s/\//\\\\/g; | ||||
57 | $extraslash = "\\"; | ||||
58 | } | ||||
59 | if ( $^O =~ /linux/i) { | ||||
60 | $extraslash = "\\"; | ||||
61 | } | ||||
62 | |||||
63 | $systemcall = $msidb . " -d " . $fulldatabasepath . " -f " . $workdir . " -e " . $extraslash . "*"; | ||||
64 | $returnvalue = system($systemcall); | ||||
65 | |||||
66 | $infoline = "Systemcall: $systemcall\n"; | ||||
67 | push( @installer::globals::logfileinfo, $infoline); | ||||
68 | |||||
69 | if ($returnvalue) | ||||
70 | { | ||||
71 | $infoline = "ERROR: Could not execute $systemcall !\n"; | ||||
72 | push( @installer::globals::logfileinfo, $infoline); | ||||
73 | installer::exiter::exit_program("ERROR: Could not exclude tables from msi database: $fulldatabasepath !", "extract_all_tables_from_msidatabase"); | ||||
74 | } | ||||
75 | else | ||||
76 | { | ||||
77 | $infoline = "Success: Executed $systemcall successfully!\n"; | ||||
78 | push( @installer::globals::logfileinfo, $infoline); | ||||
79 | } | ||||
80 | } | ||||
81 | |||||
82 | ################################################################################# | ||||
83 | # Collecting the keys from the first line of the idt file | ||||
84 | ################################################################################# | ||||
85 | |||||
86 | sub collect_all_keys | ||||
87 | { | ||||
88 | my ($line) = @_; | ||||
89 | |||||
90 | my @allkeys = (); | ||||
91 | my $rownumber = 0; | ||||
92 | my $onekey = ""; | ||||
93 | |||||
94 | while ( $line =~ /^\s*(\S+?)\t(.*)$/ ) | ||||
95 | { | ||||
96 | $onekey = $1; | ||||
97 | $line = $2; | ||||
98 | $rownumber++; | ||||
99 | push(@allkeys, $onekey); | ||||
100 | } | ||||
101 | |||||
102 | # and the last key | ||||
103 | |||||
104 | $onekey = $line; | ||||
105 | $onekey =~ s/^\s*//g; | ||||
106 | $onekey =~ s/\s*$//g; | ||||
107 | |||||
108 | $rownumber++; | ||||
109 | push(@allkeys, $onekey); | ||||
110 | |||||
111 | return (\@allkeys, $rownumber); | ||||
112 | } | ||||
113 | |||||
114 | ################################################################################# | ||||
115 | # Analyzing the content of one line of an idt file | ||||
116 | ################################################################################# | ||||
117 | |||||
118 | sub get_oneline_hash | ||||
119 | { | ||||
120 | my ($line, $allkeys, $rownumber) = @_; | ||||
121 | |||||
122 | my $counter = 0; | ||||
123 | my %linehash = (); | ||||
124 | |||||
125 | $line =~ s/^\s*//; | ||||
126 | $line =~ s/\s*$//; | ||||
127 | |||||
128 | my $value = ""; | ||||
129 | my $onekey = ""; | ||||
130 | |||||
131 | while ( $line =~ /^(.*?)\t(.*)$/ ) | ||||
132 | { | ||||
133 | $value = $1; | ||||
134 | $line = $2; | ||||
135 | $onekey = ${$allkeys}[$counter]; | ||||
136 | $linehash{$onekey} = $value; | ||||
137 | $counter++; | ||||
138 | } | ||||
139 | |||||
140 | # the last column | ||||
141 | |||||
142 | $value = $line; | ||||
143 | $onekey = ${$allkeys}[$counter]; | ||||
144 | |||||
145 | $linehash{$onekey} = $value; | ||||
146 | |||||
147 | return \%linehash; | ||||
148 | } | ||||
149 | |||||
150 | ################################################################################# | ||||
151 | # Analyzing the content of an idt file | ||||
152 | ################################################################################# | ||||
153 | |||||
154 | sub analyze_idt_file | ||||
155 | { | ||||
156 | my ($filecontent) = @_; | ||||
157 | |||||
158 | my %table = (); | ||||
159 | # keys are written in first line | ||||
160 | my ($allkeys, $rownumber) = collect_all_keys(${$filecontent}[0]); | ||||
161 | |||||
162 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
163 | { | ||||
164 | if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } | ||||
165 | |||||
166 | my $onelinehash = get_oneline_hash(${$filecontent}[$i], $allkeys, $rownumber); | ||||
167 | my $linekey = $i - 2; # ! : The linenumber is the unique key !? Always decrease by two, because of removed first three lines. | ||||
168 | $table{$linekey} = $onelinehash; | ||||
169 | } | ||||
170 | |||||
171 | return \%table; | ||||
172 | } | ||||
173 | |||||
174 | ################################################################################# | ||||
175 | # Reading all idt files in a specified directory | ||||
176 | ################################################################################# | ||||
177 | |||||
178 | sub read_all_tables_from_msidatabase | ||||
179 | { | ||||
180 | my ($workdir) = @_; | ||||
181 | |||||
182 | my %database = (); | ||||
183 | |||||
184 | my $ext = "idt"; | ||||
185 | |||||
186 | my $allidtfiles = installer::systemactions::find_file_with_file_extension($ext, $workdir); | ||||
187 | |||||
188 | for ( my $i = 0; $i <= $#{$allidtfiles}; $i++ ) | ||||
189 | { | ||||
190 | my $onefilename = ${$allidtfiles}[$i]; | ||||
191 | my $longonefilename = $workdir . $installer::globals::separator . $onefilename; | ||||
192 | if ( ! -f $longonefilename ) { installer::exiter::exit_program("ERROR: Could not find idt file: $longonefilename!", "read_all_tables_from_msidatabase"); } | ||||
193 | my $filecontent = installer::files::read_file($longonefilename); | ||||
194 | my $idtcontent = analyze_idt_file($filecontent); | ||||
195 | my $key = $onefilename; | ||||
196 | $key =~ s/\.idt\s*$//; | ||||
197 | $database{$key} = $idtcontent; | ||||
198 | } | ||||
199 | |||||
200 | return \%database; | ||||
201 | } | ||||
202 | |||||
203 | ################################################################################# | ||||
204 | # Checking, if this is the correct database. | ||||
205 | ################################################################################# | ||||
206 | |||||
207 | sub correct_database | ||||
208 | { | ||||
209 | my ($product, $pro, $langs, $languagestringref) = @_; | ||||
210 | |||||
211 | my $correct_database = 0; | ||||
212 | |||||
213 | # Comparing $product with $installer::globals::product and | ||||
214 | # $pro with $installer::globals::pro and | ||||
215 | # $langs with $languagestringref | ||||
216 | |||||
217 | my $product_is_good = 0; | ||||
218 | |||||
219 | my $localproduct = $installer::globals::product; | ||||
220 | if ( $installer::globals::languagepack ) { $localproduct = $localproduct . "LanguagePack"; } | ||||
221 | elsif ( $installer::globals::helppack ) { $localproduct = $localproduct . "HelpPack"; } | ||||
222 | |||||
223 | if ( $product eq $localproduct ) { $product_is_good = 1; } | ||||
224 | |||||
225 | if ( $product_is_good ) | ||||
226 | { | ||||
227 | my $pro_is_good = 0; | ||||
228 | |||||
229 | if ((( $pro eq "pro" ) && ( $installer::globals::pro )) || (( $pro eq "nonpro" ) && ( ! $installer::globals::pro ))) { $pro_is_good = 1; } | ||||
230 | |||||
231 | if ( $pro_is_good ) | ||||
232 | { | ||||
233 | my $langlisthash = installer::converter::convert_stringlist_into_hash(\$langs, ","); | ||||
234 | my $langstringhash = installer::converter::convert_stringlist_into_hash($languagestringref, "_"); | ||||
235 | |||||
236 | my $not_included = 0; | ||||
237 | foreach my $onelang ( keys %{$langlisthash} ) | ||||
238 | { | ||||
239 | if ( ! exists($langstringhash->{$onelang}) ) | ||||
240 | { | ||||
241 | $not_included = 1; | ||||
242 | last; | ||||
243 | } | ||||
244 | } | ||||
245 | |||||
246 | if ( ! $not_included ) | ||||
247 | { | ||||
248 | foreach my $onelanguage ( keys %{$langstringhash} ) | ||||
249 | { | ||||
250 | if ( ! exists($langlisthash->{$onelanguage}) ) | ||||
251 | { | ||||
252 | $not_included = 1; | ||||
253 | last; | ||||
254 | } | ||||
255 | } | ||||
256 | |||||
257 | if ( ! $not_included ) { $correct_database = 1; } | ||||
258 | } | ||||
259 | } | ||||
260 | } | ||||
261 | |||||
262 | return $correct_database; | ||||
263 | } | ||||
264 | |||||
265 | ################################################################################# | ||||
266 | # Searching for the path to the reference database for this special product. | ||||
267 | ################################################################################# | ||||
268 | |||||
269 | sub get_databasename_from_list | ||||
270 | # spent 197µs (143+53) within installer::windows::update::get_databasename_from_list which was called:
# once (143µs+53µs) by installer::windows::update::readdatabase at line 328 | ||||
271 | 59 | 199µs | my ($filecontent, $languagestringref, $filename) = @_; | ||
272 | |||||
273 | my $databasepath = ""; | ||||
274 | |||||
275 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
276 | { | ||||
277 | my $line = ${$filecontent}[$i]; | ||||
278 | 14 | 28µs | if ( $line =~ /^\s*$/ ) { next; } # empty line # spent 28µs making 14 calls to installer::windows::update::CORE:match, avg 2µs/call | ||
279 | 13 | 26µs | if ( $line =~ /^\s*\#/ ) { next; } # comment line # spent 26µs making 13 calls to installer::windows::update::CORE:match, avg 2µs/call | ||
280 | |||||
281 | if ( $line =~ /^\s*(.+?)\s*\t+\s*(.+?)\s*\t+\s*(.+?)\s*\t+\s*(.+?)\s*$/ ) | ||||
282 | { | ||||
283 | my $product = $1; | ||||
284 | my $pro = $2; | ||||
285 | my $langs = $3; | ||||
286 | my $path = $4; | ||||
287 | |||||
288 | if (( $pro ne "pro" ) && ( $pro ne "nonpro" )) { installer::exiter::exit_program("ERROR: Wrong syntax in file: $filename. Only \"pro\" or \"nonpro\" allowed in column 1! Line: \"$line\"", "get_databasename_from_list"); } | ||||
289 | |||||
290 | if ( correct_database($product, $pro, $langs, $languagestringref) ) | ||||
291 | { | ||||
292 | $databasepath = $path; | ||||
293 | last; | ||||
294 | } | ||||
295 | } | ||||
296 | else | ||||
297 | { | ||||
298 | installer::exiter::exit_program("ERROR: Wrong syntax in file: $filename! Line: \"$line\"", "get_databasename_from_list"); | ||||
299 | } | ||||
300 | } | ||||
301 | |||||
302 | return $databasepath; | ||||
303 | } | ||||
304 | |||||
305 | ################################################################################# | ||||
306 | # Reading an existing database completely | ||||
307 | ################################################################################# | ||||
308 | |||||
309 | sub readdatabase | ||||
310 | # spent 697µs (58+639) within installer::windows::update::readdatabase which was called:
# once (58µs+639µs) by installer::run at line 590 of /cygdrive/c/lo/libo-master/instsetoo_native/util/C:/lo/libo-master/solenv/bin/modules/installer.pm | ||||
311 | 15 | 48µs | my ($allvariables, $languagestringref, $includepatharrayref) = @_; | ||
312 | |||||
313 | my $database = ""; | ||||
314 | my $infoline = ""; | ||||
315 | |||||
316 | if ( ! $allvariables->{'UPDATE_DATABASE_LISTNAME'} ) { installer::exiter::exit_program("ERROR: If \"UPDATE_DATABASE\" is set, \"UPDATE_DATABASE_LISTNAME\" is required.", "Main"); } | ||||
317 | my $listfilename = $allvariables->{'UPDATE_DATABASE_LISTNAME'}; | ||||
318 | |||||
319 | # Searching the list in the include paths | ||||
320 | 1 | 40µs | my $listname = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$listfilename, $includepatharrayref, 1); # spent 40µs making 1 call to installer::scriptitems::get_sourcepath_from_filename_and_includepath | ||
321 | if ( $$listname eq "" ) { installer::exiter::exit_program("ERROR: List file not found: $listfilename !", "readdatabase"); } | ||||
322 | my $completelistname = $$listname; | ||||
323 | |||||
324 | # Reading list file | ||||
325 | 1 | 403µs | my $listfile = installer::files::read_file($completelistname); # spent 403µs making 1 call to installer::files::read_file | ||
326 | |||||
327 | # Get name and path of reference database | ||||
328 | 1 | 197µs | my $databasename = get_databasename_from_list($listfile, $languagestringref, $completelistname); # spent 197µs making 1 call to installer::windows::update::get_databasename_from_list | ||
329 | |||||
330 | # If the correct database was not found, this is not necessarily an error. But in this case, this is not an update packaging process! | ||||
331 | if (( $databasename ) && ( $databasename ne "" )) # This is an update packaging process! | ||||
332 | { | ||||
333 | $installer::globals::updatedatabase = 1; | ||||
334 | installer::logger::print_message( "... update process, using database $databasename ...\n" ); | ||||
335 | $infoline = "\nDatabase found in $completelistname: \"$databasename\"\n\n"; | ||||
336 | # Saving in global variable | ||||
337 | $installer::globals::updatedatabasepath = $databasename; | ||||
338 | } | ||||
339 | else | ||||
340 | { | ||||
341 | $infoline = "\nNo database found in $completelistname. This is no update process!\n\n"; | ||||
342 | } | ||||
343 | push( @installer::globals::logfileinfo, $infoline); | ||||
344 | |||||
345 | if ( $installer::globals::updatedatabase ) | ||||
346 | { | ||||
347 | if ( ! -f $databasename ) { installer::exiter::exit_program("ERROR: Could not find reference database: $databasename!", "readdatabase"); } | ||||
348 | |||||
349 | my $msifilename = $databasename; | ||||
350 | installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$msifilename); | ||||
351 | |||||
352 | installer::logger::include_timestamp_into_logfile("Performance Info: readdatabase start"); | ||||
353 | |||||
354 | # create directory for unpacking | ||||
355 | my $databasedir = installer::systemactions::create_directories("database", $languagestringref); | ||||
356 | |||||
357 | # copy database | ||||
358 | my $fulldatabasepath = $databasedir . $installer::globals::separator . $msifilename; | ||||
359 | installer::systemactions::copy_one_file($databasename, $fulldatabasepath); | ||||
360 | |||||
361 | installer::logger::include_timestamp_into_logfile("Performance Info: readdatabase: before extracting tables"); | ||||
362 | |||||
363 | # extract all tables from database | ||||
364 | extract_all_tables_from_msidatabase($fulldatabasepath, $databasedir); | ||||
365 | |||||
366 | installer::logger::include_timestamp_into_logfile("Performance Info: readdatabase: before reading tables"); | ||||
367 | |||||
368 | # read all tables | ||||
369 | $database = read_all_tables_from_msidatabase($databasedir); | ||||
370 | |||||
371 | # Test output: | ||||
372 | |||||
373 | # foreach my $key1 ( keys %{$database} ) | ||||
374 | # { | ||||
375 | # print "Test1: $key1\n"; | ||||
376 | # foreach my $key2 ( keys %{$database->{$key1}} ) | ||||
377 | # { | ||||
378 | # print "\tTest2: $key2\n"; | ||||
379 | # foreach my $key3 ( keys %{$database->{$key1}->{$key2}} ) | ||||
380 | # { | ||||
381 | # print "\t\tTest3: $key3: $database->{$key1}->{$key2}->{$key3}\n"; | ||||
382 | # } | ||||
383 | # } | ||||
384 | # } | ||||
385 | |||||
386 | # Example: File table | ||||
387 | |||||
388 | # my $filetable = $database->{'File'}; | ||||
389 | # foreach my $linenumber ( keys %{$filetable} ) | ||||
390 | # { | ||||
391 | # print "Test Filenumber: $linenumber\n"; | ||||
392 | # foreach my $key ( keys %{$filetable->{$linenumber}} ) | ||||
393 | # { | ||||
394 | # print "\t\tTest: $key: $filetable->{$linenumber}->{$key}\n"; | ||||
395 | # } | ||||
396 | # } | ||||
397 | |||||
398 | # Example: Searching for ProductCode in table Property | ||||
399 | |||||
400 | # my $column1 = "Property"; | ||||
401 | # my $column2 = "Value"; | ||||
402 | # my $searchkey = "ProductCode"; | ||||
403 | # my $propertytable = $database->{'Property'}; | ||||
404 | # foreach my $linenumber ( keys %{$propertytable} ) | ||||
405 | # { | ||||
406 | # if ( $propertytable->{$linenumber}->{$column1} eq $searchkey ) | ||||
407 | # { | ||||
408 | # print("Test: $searchkey : $propertytable->{$linenumber}->{$column2}\n"); | ||||
409 | # } | ||||
410 | # } | ||||
411 | |||||
412 | installer::logger::include_timestamp_into_logfile("Performance Info: readdatabase end"); | ||||
413 | } | ||||
414 | |||||
415 | return $database; | ||||
416 | } | ||||
417 | |||||
418 | ################################################################################# | ||||
419 | # Files can be included in merge modules. This is also important for update. | ||||
420 | ################################################################################# | ||||
421 | |||||
422 | sub readmergedatabase | ||||
423 | { | ||||
424 | my ( $mergemodules, $languagestringref, $includepatharrayref ) = @_; | ||||
425 | |||||
426 | installer::logger::include_timestamp_into_logfile("Performance Info: readmergedatabase start"); | ||||
427 | |||||
428 | my $mergemoduledir = installer::systemactions::create_directories("mergedatabase", $languagestringref); | ||||
429 | |||||
430 | my %allmergefiles = (); | ||||
431 | |||||
432 | $installer::globals::mergemodulenumber = $#{$mergemodules} + 1; | ||||
433 | |||||
434 | foreach my $mergemodule ( @{$mergemodules} ) | ||||
435 | { | ||||
436 | my $filename = $mergemodule->{'Name'}; | ||||
437 | my $mergefile = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$filename, $includepatharrayref, 1); | ||||
438 | |||||
439 | if ( $$mergefile eq "" ) { installer::exiter::exit_program("ERROR: msm file not found: $filename !", "readmergedatabase"); } | ||||
440 | my $completesource = $$mergefile; | ||||
441 | |||||
442 | my $mergegid = $mergemodule->{'gid'}; | ||||
443 | my $workdir = $mergemoduledir . $installer::globals::separator . $mergegid; | ||||
444 | if ( ! -d $workdir ) { installer::systemactions::create_directory($workdir); } | ||||
445 | |||||
446 | my $completedest = $workdir . $installer::globals::separator . $filename; | ||||
447 | installer::systemactions::copy_one_file($completesource, $completedest); | ||||
448 | if ( ! -f $completedest ) { installer::exiter::exit_program("ERROR: msm file not found: $completedest !", "readmergedatabase"); } | ||||
449 | |||||
450 | # extract all tables from database | ||||
451 | extract_all_tables_from_msidatabase($completedest, $workdir); | ||||
452 | |||||
453 | # read all tables | ||||
454 | my $onemergefile = read_all_tables_from_msidatabase($workdir); | ||||
455 | |||||
456 | $allmergefiles{$mergegid} = $onemergefile; | ||||
457 | } | ||||
458 | |||||
459 | foreach my $mergefilegid ( keys %allmergefiles ) | ||||
460 | { | ||||
461 | my $onemergefile = $allmergefiles{$mergefilegid}; | ||||
462 | my $filetable = $onemergefile->{'File'}; | ||||
463 | |||||
464 | foreach my $linenumber ( keys %{$filetable} ) | ||||
465 | { | ||||
466 | # Collecting all files from merge modules in global hash | ||||
467 | $installer::globals::mergemodulefiles{$filetable->{$linenumber}->{'File'}} = 1; | ||||
468 | } | ||||
469 | } | ||||
470 | |||||
471 | installer::logger::include_timestamp_into_logfile("Performance Info: readmergedatabase end"); | ||||
472 | } | ||||
473 | |||||
474 | ################################################################################# | ||||
475 | # Creating several useful hashes from old database | ||||
476 | ################################################################################# | ||||
477 | |||||
478 | sub create_database_hashes | ||||
479 | { | ||||
480 | my ( $database ) = @_; | ||||
481 | |||||
482 | # 1. Hash ( Component -> UniqueFileName ), required in File table. | ||||
483 | # Read from File table. | ||||
484 | |||||
485 | my %uniquefilename = (); | ||||
486 | my %allupdatesequences = (); | ||||
487 | my %allupdatecomponents = (); | ||||
488 | my %allupdatefileorder = (); | ||||
489 | my %allupdatecomponentorder = (); | ||||
490 | my %revuniquefilename = (); | ||||
491 | my %revshortfilename = (); | ||||
492 | my %shortdirname = (); | ||||
493 | my %componentid = (); | ||||
494 | my %componentidkeypath = (); | ||||
495 | my %alloldproperties = (); | ||||
496 | my %allupdatelastsequences = (); | ||||
497 | my %allupdatediskids = (); | ||||
498 | |||||
499 | my $filetable = $database->{'File'}; | ||||
500 | |||||
501 | foreach my $linenumber ( keys %{$filetable} ) | ||||
502 | { | ||||
503 | my $comp = $filetable->{$linenumber}->{'Component_'}; | ||||
504 | my $uniquename = $filetable->{$linenumber}->{'File'}; | ||||
505 | my $filename = $filetable->{$linenumber}->{'FileName'}; | ||||
506 | my $sequence = $filetable->{$linenumber}->{'Sequence'}; | ||||
507 | |||||
508 | my $shortname = ""; | ||||
509 | if ( $filename =~ /^\s*(.*?)\|\s*(.*?)\s*$/ ) | ||||
510 | { | ||||
511 | $shortname = $1; | ||||
512 | $filename = $2; | ||||
513 | } | ||||
514 | |||||
515 | # unique is the combination of $component and $filename | ||||
516 | my $key = "$comp/$filename"; | ||||
517 | |||||
518 | if ( exists($uniquefilename{$key}) ) { installer::exiter::exit_program("ERROR: Component/FileName \"$key\" is not unique in table \"File\" !", "create_database_hashes"); } | ||||
519 | |||||
520 | my $value = $uniquename; | ||||
521 | if ( $shortname ne "" ) { $value = "$uniquename;$shortname"; } | ||||
522 | $uniquefilename{$key} = $value; # saving the unique keys and short names in hash | ||||
523 | |||||
524 | # Saving reverse keys too | ||||
525 | $revuniquefilename{$uniquename} = $key; | ||||
526 | if ( $shortname ne "" ) { $revshortfilename{$shortname} = $key; } | ||||
527 | |||||
528 | # Saving Sequences for unique names (and also components) | ||||
529 | $allupdatesequences{$uniquename} = $sequence; | ||||
530 | $allupdatecomponents{$uniquename} = $comp; | ||||
531 | |||||
532 | # Saving unique names and components for sequences | ||||
533 | $allupdatefileorder{$sequence} = $uniquename; | ||||
534 | $allupdatecomponentorder{$sequence} = $comp; | ||||
535 | } | ||||
536 | |||||
537 | # 2. Hash, required in Directory table. | ||||
538 | |||||
539 | my $dirtable = $database->{'Directory'}; | ||||
540 | |||||
541 | foreach my $linenumber ( keys %{$dirtable} ) | ||||
542 | { | ||||
543 | my $dir = $dirtable->{$linenumber}->{'Directory'}; # this is a unique name | ||||
544 | my $defaultdir = $dirtable->{$linenumber}->{'DefaultDir'}; | ||||
545 | |||||
546 | my $shortname = ""; | ||||
547 | if ( $defaultdir =~ /^\s*(.*?)\|\s*(.*?)\s*$/ ) | ||||
548 | { | ||||
549 | $shortname = $1; | ||||
550 | $shortdirname{$dir} = $shortname; # collecting only the short names | ||||
551 | } | ||||
552 | } | ||||
553 | |||||
554 | # 3. Hash, collecting info from Component table. | ||||
555 | # ComponentID and KeyPath have to be reused. | ||||
556 | |||||
557 | my $comptable = $database->{'Component'}; | ||||
558 | |||||
559 | foreach my $linenumber ( keys %{$comptable} ) | ||||
560 | { | ||||
561 | my $comp = $comptable->{$linenumber}->{'Component'}; | ||||
562 | my $compid = $comptable->{$linenumber}->{'ComponentId'}; | ||||
563 | my $keypath = $comptable->{$linenumber}->{'KeyPath'}; | ||||
564 | |||||
565 | $componentid{$comp} = $compid; | ||||
566 | $componentidkeypath{$comp} = $keypath; | ||||
567 | } | ||||
568 | |||||
569 | # 4. Hash, property table, required for ProductCode and Installlocation. | ||||
570 | |||||
571 | my $proptable = $database->{'Property'}; | ||||
572 | |||||
573 | foreach my $linenumber ( keys %{$proptable} ) | ||||
574 | { | ||||
575 | my $prop = $proptable->{$linenumber}->{'Property'}; | ||||
576 | my $value = $proptable->{$linenumber}->{'Value'}; | ||||
577 | |||||
578 | $alloldproperties{$prop} = $value; | ||||
579 | } | ||||
580 | |||||
581 | # 5. Media table, getting last sequence | ||||
582 | |||||
583 | my $mediatable = $database->{'Media'}; | ||||
584 | $installer::globals::updatelastsequence = 0; | ||||
585 | |||||
586 | foreach my $linenumber ( keys %{$mediatable} ) | ||||
587 | { | ||||
588 | my $cabname = $mediatable->{$linenumber}->{'Cabinet'}; | ||||
589 | my $lastsequence = $mediatable->{$linenumber}->{'LastSequence'}; | ||||
590 | my $diskid = $mediatable->{$linenumber}->{'DiskId'}; | ||||
591 | $allupdatelastsequences{$cabname} = $lastsequence; | ||||
592 | $allupdatediskids{$cabname} = $diskid; | ||||
593 | |||||
594 | if ( $lastsequence > $installer::globals::updatelastsequence ) { $installer::globals::updatelastsequence = $lastsequence; } | ||||
595 | } | ||||
596 | |||||
597 | $installer::globals::updatesequencecounter = $installer::globals::updatelastsequence; | ||||
598 | |||||
599 | return (\%uniquefilename, \%revuniquefilename, \%revshortfilename, \%allupdatesequences, \%allupdatecomponents, \%allupdatefileorder, \%allupdatecomponentorder, \%shortdirname, \%componentid, \%componentidkeypath, \%alloldproperties, \%allupdatelastsequences, \%allupdatediskids); | ||||
600 | } | ||||
601 | |||||
602 | |||||
603 | 1 | 9µs | 1; | ||
# spent 53µs within installer::windows::update::CORE:match which was called 27 times, avg 2µs/call:
# 14 times (28µs+0s) by installer::windows::update::get_databasename_from_list at line 278, avg 2µs/call
# 13 times (26µs+0s) by installer::windows::update::get_databasename_from_list at line 279, avg 2µs/call |