1 # ======================================================================
4 # Copyright 2003 Sony Online Entertainment, Inc.
7 # ======================================================================
9 # Used to upgrade SWG customization data from an older database format
10 # to a newer database format. Note the exact upgrade logic needed will
11 # be different in any upgrade situation, but this should be a good template
12 # for most of the code in the event of another customization data upgrade
13 # some time in the future.
15 # Perl modules DBI and DBD::Oracle must be installed to run this tool. See www.perl.com for info on getting these modules.
16 # You must have PERL5LIB (or PERLLIB) set to your mapping for //depot/swg/current/tools/perllib.
22 # ======================================================================
24 # ======================================================================
29 my $password = "changeme";
30 my $databaseName = "swodb";
37 my $limitRowCount = 0;
40 my $defaultFilename = '../dsrc/sku.0/sys.shared/compiled/game/customization/customization_id_manager.mif';
41 my $customizationIdManagerFilename = $defaultFilename;
43 # ======================================================================
47 print "Calling syntax:\n";
48 print "\tperl -w custUpgrade.pl -u <database username> [-p <database password>] [-D <database>] [-d] [-n] [-U] [-c <commit count>] [-l <limit row count>] [-m <pathToCustomizationIdManagerMifFile>] [-s <progressOutputStep>]\n";
49 print "Option description:\n";
50 print "\t-u: specifies the name of the user for the Oracle database.\n";
51 print "\t-p: [optional] specifies the password for the user of the Oracle database. Default: changeme.\n";
52 print "\t-D: [optional] specifies the database to attach to. Default: swodb.\n";
53 print "\t-d: [optional] turn on extensive debug-level output.\n";
54 print "\t-n: [optional] do not make changes to the database, just print what would have happened.\n";
55 print "\t-U: [optional] Upgrade customization data in the database.\n";
56 print "\t-c: [optional] commit every 'commit count' number of rows processed, or 0 for single commit at the end. Default: 0.\n";
57 print "\t-l: [optional] limit database processing to first <limit row count> rows or 0 for no limit. Default: 0.\n";
58 print "\t-m: [optional] specify path to CustomizationIdManager's mif version of initialization file. Default: $defaultFilename\n";
59 print "\t-s: [optional] print a progress line every progressStep percent or 0 if no output. Default: 0.\n";
60 print "\t-h: [optional] print this help info.\n";
63 # ======================================================================
70 while (defined($ARGV[0]) && ($ARGV[0] =~ m/^-(.*)$/))
77 print "-u option missing <database username> specification.\n";
83 print "<username: $userName>\n" if $debug;
93 print "-p option missing <password> specification.\n";
99 print "<password: $password>\n" if $debug;
106 # Grab database name.
109 print "-D option missing <database> specification.\n";
114 $databaseName = $ARGV[1];
115 print "<database: $databaseName>\n" if $debug;
123 $Customization::Debug
= 1;
142 print "-c option missing <commit count> specification.\n";
147 $commitCount = $ARGV[1];
148 print "<commit count: $commitCount>\n" if $debug;
158 print "-l option missing <limit row count> specification.\n";
163 $limitRowCount = $ARGV[1];
164 print "<limitRowCount: $limitRowCount>\n" if $debug;
174 print "-m option missing <CustomizationIdManager MIF file> specification.\n";
179 $customizationIdManagerFilename = $ARGV[1];
180 print "<customizationIdManagerFilename: $customizationIdManagerFilename\n" if $debug;
190 print "-s option missing <progressStepPercent> specification.\n";
195 $progressStep = $ARGV[1];
196 print "<progressStep: $progressStep>\n" if $debug;
203 warn "unknown option [$1].";
207 # Process next argument.
211 # Check for missing options.
212 if (length $userName < 1)
214 print "missing -u username option.\n";
218 # Show help as needed.
219 if ($showHelp || ($exitCode != 0))
226 # ======================================================================
227 # input: old-style customization ascii string.
228 # output: new-style customization binary data (as string) (unescaped --- can contain embedded NULLs).
229 # ======================================================================
234 my $oldString = shift;
236 # fill directory contents from old string.
239 my $rc = getVariableInfoFromOldString
(%variableInfo, $oldString);
242 warn "convertOldToNew:failed to get variable info from old-style customization data string [$oldString]\n";
246 return createNewDataFromVariableInfo
(%variableInfo);
249 # ======================================================================
255 # Open the database connection.
256 my $dbHandle = DBI
->connect("dbi:Oracle:$databaseName", $userName, $password, { RaiseError
=> 1, AutoCommit
=> 0 });
257 error
("failed to open database: [$DBI::errstr]") if !defined($dbHandle);
258 print "<connection: opened connection to database [$databaseName] as user [$userName] successfully.>\n" if $debug;
260 # Find # rows that match our criteria of non-zero-length customization data.
261 my $totalRowCount = 0;
263 my $statementHandle = $dbHandle->prepare("SELECT COUNT(*) FROM tangible_objects WHERE LENGTH(appearance_data) > 0") or die $dbHandle->errstr;
264 $statementHandle->execute() or die $statementHandle->errstr;
266 my @row = $statementHandle->fetchrow_array;
267 die($statementHandle->errString) if !@row;
269 $totalRowCount = $row[0];
270 print "<totalRowCount: $totalRowCount>\n" if $debug;
273 # Progress bar uses limitRowCount or totalRowCount depending on whether row limiting is in effect.
274 my $progressTotalRowCount = $totalRowCount;
275 if (($limitRowCount > 0) && ($limitRowCount < $totalRowCount))
277 $progressTotalRowCount = $limitRowCount;
281 my $uncommittedRowCount = 0;
282 my $totalCommittedRowCount = 0;
283 my $processedRowCount = 0;
284 my $failedRowCount = 0;
285 my $sumOldStringSize = 0;
286 my $sumNewDataSize = 0;
287 my $sumNewStringSize = 0;
288 my $lastPrintedPercent = 0;
291 # Prepare the SELECT statement.
292 my $statementHandle = $dbHandle->prepare("SELECT object_id, appearance_data FROM tangible_objects WHERE LENGTH(appearance_data) > 0") or die $dbHandle->errstr;
293 $statementHandle->execute() or die $statementHandle->errstr;
295 # Prepare the UPDATE statement.
296 my $updateStatementHandle = $dbHandle->prepare("UPDATE tangible_objects SET appearance_data = ? WHERE object_id = ?") or die $dbHandle->errstr;
298 while (my @row = $statementHandle->fetchrow_array)
300 # Validate row entry count.
301 die "Returned row has " . @row . "entries, expecting 2." if (@row != 2);
303 ++$processedRowCount;
305 # Retrieve object id and old customization data.
306 my $objectId = $row[0];
307 my $oldCustomizationString = $row[1];
308 print "<row: num=[$processedRowCount] id=[$objectId]: string=[$oldCustomizationString]>\n" if $debug;
310 # Keep track of old customization string size.
311 $sumOldStringSize += length $oldCustomizationString;
314 my $newCustomizationData = convertOldToNew
($oldCustomizationString);
315 my $newDataLength = length $newCustomizationData;
317 if (!defined($newCustomizationData) || ($newDataLength < 1))
320 print STDERR
"failed to convert old customization data [$oldCustomizationString] (total failed rows=$failedRowCount).\n";
324 # Track new unescaped binary data length.
325 $sumNewDataSize += $newDataLength;
327 # Convert binary data to escaped string form.
328 my $newCustomizationString = escapeBinaryData
($newCustomizationData);
330 # Track new escaped string data length.
331 my $newStringLength = length $newCustomizationString;
332 if (!defined($newCustomizationString) || ($newStringLength < 1))
335 print STDERR
"failed to convert new binary customization data [$newCustomizationData] to string (total failed rows=$failedRowCount).\n";
339 $sumNewStringSize += length $newCustomizationString;
341 # Update the database with new entry.
344 # Execute the update.
345 $updateStatementHandle->execute($newCustomizationString, $objectId) or die $statementHandle->errstr;
347 # Check if we should commit.
348 ++$uncommittedRowCount;
350 if (($commitCount != 0) && ($uncommittedRowCount >= $commitCount))
353 my $returnCode = $dbHandle->commit or die $dbHandle->errstr;
355 $totalCommittedRowCount += $uncommittedRowCount;
356 print "<commit: $uncommittedRowCount rows committed now, $processedRowCount total, returnCode=$returnCode.>\n" if $debug;
358 $uncommittedRowCount = 0;
363 print "<update: would do UPDATE tangible_objects SET appearance_data = (" . $newStringLength . " byte string) WHERE object_id = [$objectId]>\n" if $debug;
368 # Handle progress monitoring.
369 if ($progressStep > 0)
371 my $progressPercent = 100.0 * $processedRowCount / $progressTotalRowCount;
372 if ($progressPercent >= ($lastPrintedPercent + $progressStep))
374 $lastPrintedPercent = $progressPercent;
375 printf("progress: %d%% complete.\n", $lastPrintedPercent);
379 # Handle row limiting.
380 if (($limitRowCount > 0) && ($processedRowCount >= $limitRowCount))
382 print "<limitRowCount: specified row count limit [$limitRowCount] hit, finishing now.>\n" if $debug;
391 my $returnCode = $dbHandle->commit or die $dbHandle->errstr;
393 $totalCommittedRowCount += $uncommittedRowCount;
394 print "<commit: $uncommittedRowCount rows committed now, $processedRowCount total, returnCode=$returnCode.>\n" if $debug;
396 $uncommittedRowCount = 0;
399 # Close the database connection.
400 $returnCode = $dbHandle->disconnect or warn $dbHandle->errstr;
401 print "<disconnect: return code $returnCode>" if $debug;
404 print "Completed upgrade process, printing statistics.\n";
405 print "\tTotal rows processed: $processedRowCount\n";
406 print "\tTotal rows changed: $totalCommittedRowCount\n\n";
409 $oldAverage = ($sumOldStringSize / $processedRowCount) if $processedRowCount > 0;
410 printf("\tTotal old customization string data: $sumOldStringSize bytes (average: %.2f bytes each)\n", $oldAverage) if $processedRowCount > 0;
412 my $newStringCount = $processedRowCount - $failedRowCount;
414 $newAverage = ($sumNewStringSize / $newStringCount) if $newStringCount > 0;
415 printf("\tTotal new customization string data: $sumNewStringSize bytes (average: %.2f bytes each)\n", $newAverage) if $newStringCount > 0;
417 my $compressionFraction = $newAverage / $oldAverage;
418 printf "\tCompressed to %.2f%% of original size.\n", $compressionFraction * 100;
420 my $difference = $sumNewStringSize - $sumNewDataSize;
421 printf("\tTotal overhead for binary data escaping: $difference bytes (%.2f%% increase).\n", 100.0 * (($sumNewStringSize / $sumNewDataSize) - 1.0)) if $sumNewDataSize > 0;
424 # ======================================================================
425 # Program Starts Here
426 # ======================================================================
432 initializeCustomization
($customizationIdManagerFilename);
437 # ======================================================================