| 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 | installer::windows::update::BEGIN@30 |
| 1 | 1 | 1 | 143µs | 197µs | installer::windows::update::get_databasename_from_list |
| 1 | 1 | 1 | 58µs | 697µs | installer::windows::update::readdatabase |
| 27 | 2 | 1 | 53µs | 53µs | installer::windows::update::CORE:match (opcode) |
| 1 | 1 | 1 | 16µs | 18µs | installer::windows::update::BEGIN@31 |
| 1 | 1 | 1 | 15µs | 16µs | installer::windows::update::BEGIN@33 |
| 1 | 1 | 1 | 15µs | 17µs | installer::windows::update::BEGIN@34 |
| 1 | 1 | 1 | 14µs | 16µs | installer::windows::update::BEGIN@32 |
| 1 | 1 | 1 | 14µs | 16µs | installer::windows::update::BEGIN@35 |
| 0 | 0 | 0 | 0s | 0s | installer::windows::update::analyze_idt_file |
| 0 | 0 | 0 | 0s | 0s | installer::windows::update::collect_all_keys |
| 0 | 0 | 0 | 0s | 0s | installer::windows::update::correct_database |
| 0 | 0 | 0 | 0s | 0s | installer::windows::update::create_database_hashes |
| 0 | 0 | 0 | 0s | 0s | installer::windows::update::extract_all_tables_from_msidatabase |
| 0 | 0 | 0 | 0s | 0s | installer::windows::update::get_oneline_hash |
| 0 | 0 | 0 | 0s | 0s | installer::windows::update::read_all_tables_from_msidatabase |
| 0 | 0 | 0 | 0s | 0s | installer::windows::update::readmergedatabase |
| 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 | 4 | 24µs | my ($filecontent, $languagestringref, $filename) = @_; | ||
| 272 | |||||
| 273 | my $databasepath = ""; | ||||
| 274 | |||||
| 275 | 41 | 163µs | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||
| 276 | { | ||||
| 277 | my $line = ${$filecontent}[$i]; | ||||
| 278 | 1 | 1µs | 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 | 11µs | 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 | 14 | 44µ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 | 1 | 4µs | 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 |