add the build tools

This commit is contained in:
DarthArgus
2018-01-20 13:55:01 -06:00
commit b8ed389410
268 changed files with 387585 additions and 0 deletions

41
README.md Normal file
View File

@@ -0,0 +1,41 @@
# Star Wars Galaxies Source Code (C++) Build Tools
This is the main server code. Please feel free to contribute merge/pull requests, or fork the code to create variations. Please keep the license and credit information intact.
The majority of the work is thanks to Devcodex, with more fixes and optimizations provided by DarthArgus.
# src Repo:
# Main Branches
* master - stable, no debug flags
* testing - bleeding edge, works in progress, probably stable
# Works in progress
* testing-64 - fully 64 bit version thatbuilds but doesn't run, some typedefs and things are wrong
# Building
Only use the Debug and Release targets unless you want to work on 64 bit. For local testing, and non-live builds set MODE=Release or MODE=debug in build_linux.sh.
For production, user facing builds, set MODE=MINSIZEREL for profile built, heavily optimized versions of the binaries.
## Profiling and Using Profiles
To generate new profiles, build SWG with MODE=RELWITHDEBINFO.
Add export LLVM_PROFILE_FILE="output-%p.profraw" to your startServer.sh file.
WHILE THE SERVER IS RUNNING do a ps -a to get the pid's of each SWG executable. And take note of which ones are which.
After you cleanly exit (shutdown) the server, and ctrl+c the LoginServer, move each output-pid.profraw to a folder named for it's process.
Then, proceed to combine them into usable profiles for the compiler:
llvm-profdata merge -output=code.profdata output-*.profraw
Finally, then replace the profdata files with the updated versions, within the src/ tree.
See http://clang.llvm.org/docs/UsersManual.html#profiling-with-instrumentation for more information.
# Buy Darth A Caffinated Beverage
bitcoin:16e1QRRmnBmod3RLtdDMa5muKBGRXE3Kmh

330
build_linux.sh Executable file
View File

@@ -0,0 +1,330 @@
#!/bin/bash
basedir=$PWD
PATH=$PATH:$basedir/build/bin
DBSERVICE=
DBUSERNAME=
DBPASSWORD=
HOSTIP=
CLUSTERNAME=
NODEID=
DSRC_DIR=
DATA_DIR=
GIT_URL="https://darth-swg@bitbucket.org/stellabellumswg/dsrc.git"
GIT_REPO_SRC=${GIT_URL}src.git
GIT_REPO_DSRC=${GIT_URL}dsrc.git
GIT_REPO_CONFIG=${GIT_URL}configs.git
GIT_REPO_DATA=${GIT_URL}data.git
# Debug and Release are for testing and not public servers, they lack optimizations
MODE=Release
#MODE=Debug
# Public/high load release builds - heavily optimized bins
#MODE=MINSIZEREL
# Builds binaries to generate profdata
#MODE=RELWITHDEBINFO
if [ ! -d $basedir/build ]
then
mkdir $basedir/build
fi
if [ ! -f $basedir/.setup ]; then
if [[ $(lsb_release -a) =~ .*Ubuntu.* ]] || [ -f "/etc/debian_version" ]
then
read -p "!!!ONLY RUN ONCE!!! Do you want to install dependencies (y/n)?" response
response=${response,,} # tolower
if [[ $response =~ ^(yes|y| ) ]]; then
$basedir/utils/init/debian.sh
source /etc/profile.d/java.sh
source /etc/profile.d/oracle.sh
touch $basedir/.setup
echo "Please login and out or reboot as changes have been made to your PATH "
fi
fi
fi
read -p "Do you want to pull/update git? (y/n) " response
response=${response,,} # tolower
if [[ $response =~ ^(yes|y| ) ]]; then
# update main repo
git pull
# update or clone each sub-repo
if [ ! -d $basedir/src ]; then
git clone $GIT_REPO_SRC src
else
cd $basedir/src
git pull
cd $basedir
fi
if [ ! -d $basedir/dsrc ]; then
git clone $GIT_REPO_DSRC dsrc
else
cd $basedir/dsrc
git pull
cd $basedir
fi
if [ ! -d $basedir/configs ]; then
git clone $GIT_REPO_CONFIG configs
else
cd $basedir/configs
git pull
cd $basedir
fi
fi
read -p "Do you want to recompile the server code (C++) now? (y/n) " response
response=${response,,} # tolower
if [[ $response =~ ^(yes|y| ) ]]; then
cd $basedir/build
# prefer clang
if type clang &> /dev/null; then
export CC=clang
export CXX=clang++
fi
if [ $(arch) == "x86_64" ]; then
export LDFLAGS=-L/usr/lib32
export CMAKE_PREFIX_PATH="/usr/lib32:/lib32:/usr/lib/i386-linux-gnu:/usr/include/i386-linux-gnu"
cmake -DCMAKE_C_FLAGS=-m32 \
-DCMAKE_CXX_FLAGS=-m32 \
-DCMAKE_EXE_LINKER_FLAGS=-m32 \
-DCMAKE_MODULE_LINKER_FLAGS=-m32 \
-DCMAKE_SHARED_LINKER_FLAGS=-m32 \
-DCMAKE_BUILD_TYPE=$MODE \
$basedir/src
else
cmake $basedir/src -DCMAKE_BUILD_TYPE=$MODE
fi
make -j$(nproc)
if [[ $MODE =~ ^(Release) ]]; then
strip -s bin/*
fi
cd $basedir
fi
read -p "Do you want to build the config environment now? (y/n) " response
response=${response,,} # tolower
if [[ $response =~ ^(yes|y| ) ]]; then
# Prompt for configuration environment.
read -p "Configure environment (local, live, tc, design)? You probably want local. " config_env
# Make sure the configuration environment exists.
if [ ! -d $basedir/configs/$config_env ]; then
echo "Invalid configuration environment."
exit
fi
echo "Enter your IP address (LAN for port forwarding or internal, outside IP for DMZ)"
read HOSTIP
echo "Enter the DSN for the database connection "
read DBSERVICE
echo "Enter the database username "
read DBUSERNAME
echo "Enter the database password "
read DBPASSWORD
echo "Enter a name for the galaxy cluster "
read CLUSTERNAME
if [ -d $basedir/exe ]; then
rm -rf $basedir/exe
fi
mkdir -p $basedir/exe/linux/logs
mkdir -p $basedir/exe/shared
ln -s $basedir/build/bin $basedir/exe/linux/bin
cp -u $basedir/configs/$config_env/linux/* $basedir/exe/linux
cp -u $basedir/configs/$config_env/shared/* $basedir/exe/shared
for filename in $(find $basedir/exe -name '*.cfg'); do
sed -i -e "s@DBSERVICE@$DBSERVICE@g" -e "s@DBUSERNAME@$DBUSERNAME@g" -e "s@DBPASSWORD@$DBPASSWORD@g" -e "s@CLUSTERNAME@$CLUSTERNAME@g" -e "s@HOSTIP@$HOSTIP@g" $filename
done
#
# Generate other config files if their template exists.
#
# Generate at least 1 node that is the /etc/hosts IP.
$basedir/utils/build_node_list.sh
fi
if [ ! -d $basedir/data ]; then
read -p "Symlink to data directory (y/n)? " remote_dsrc_response
remote_dsrc_response=${remote_dsrc_response,,}
if [[ $remote_dsrc_response =~ ^(yes|y| ) ]]; then
read -p "Enter target data directory " DATA_DIR
ln -s $DATA_DIR ./data
fi
fi
read -p "Do you want to recompile the scripts (.java)? (y/n) " response
response=${response,,} # tolower
if [[ $response =~ ^(yes|y| ) ]]; then
#prepare environment to run data file builders
oldPATH=$PATH
PATH=$basedir/build/bin:$PATH
read -p "Do you wanna use multi-core building (default) or stick with the safe option? You may need to rerun the single version if there are stragglers. (multi/safe) " response
response=${response,,}
if [[ $response =~ ^(multi|m| ) ]]; then
$basedir/utils/build_java_multi.sh
else
$basedir/utils/build_java.sh
fi
PATH=$oldPATH
fi
buildTemplates=false
read -p "Do you want to build the mIFF files (.mif)? (y/n) " response
response=${response,,}
if [[ $response =~ ^(yes|y| ) ]]; then
#prepare environment to run data file builders
oldPATH=$PATH
PATH=$basedir/build/bin:$PATH
$basedir/utils/build_miff.sh
buildTemplates=true
PATH=$oldPATH
fi
read -p "Do you want to build the datatables (.tab)? (y/n) " response
response=${response,,}
if [[ $response =~ ^(yes|y| ) ]]; then
#prepare environment to run data file builders
oldPATH=$PATH
PATH=$basedir/build/bin:$PATH
read -p "Do you wanna use multi-core building (default) or stick with the safe option? You may need to rerun the single version if there are stragglers. (multi/safe) " response
response=${response,,}
if [[ $response =~ ^(multi|m| ) ]]; then
$basedir/utils/build_tab_multi.sh
else
$basedir/utils/build_tab.sh
fi
buildTemplates=true
PATH=$oldPATH
fi
read -p "Do you want to build the template files (.tpf)? (y/n) " response
response=${response,,}
if [[ $response =~ ^(yes|y| ) ]]; then
#prepare environment to run data file builders
oldPATH=$PATH
PATH=$basedir/build/bin:$PATH
read -p "Do you wanna use multi-core building (default) or stick with the safe option? You may need to rerun the single version if there are stragglers. (multi/safe) " response
response=${response,,}
if [[ $response =~ ^(multi|m| ) ]]; then
$basedir/utils/build_tpf_multi.sh
else
$basedir/utils/build_tpf.sh
fi
buildTemplates=true
PATH=$oldPATH
fi
if [[ $buildTemplates = false ]]; then
read -p "Do you want to build the Object Template or Quest CRC files? (y/n) " response
response=${response,,}
if [[ $response =~ ^(yes|y| ) ]]; then
buildTemplates=true
fi
fi
templatesLoaded=false
if [[ $buildTemplates = true ]]; then
echo "Object Template and Quest CRC files will now be built and re-imported into the database."
if [[ -z "$DBSERVICE" ]]; then
echo "Enter the DSN for the database connection "
read DBSERVICE
fi
if [[ -z "$DBUSERNAME" ]]; then
echo "Enter the database username "
read DBUSERNAME
fi
if [[ -z "$DBPASSWORD" ]]; then
echo "Enter the database password "
read DBPASSWORD
fi
#prepare environment to run data file builders
oldPATH=$PATH
PATH=$basedir/build/bin:$PATH
$basedir/utils/build_object_template_crc_string_tables.py
$basedir/utils/build_quest_crc_string_tables.py
cd $basedir/src/game/server/database
echo "Loading template list"
perl ./templates/processTemplateList.pl < $basedir/dsrc/sku.0/sys.server/built/game/misc/object_template_crc_string_table.tab > $basedir/build/templates.sql
sqlplus ${DBUSERNAME}/${DBPASSWORD}@${DBSERVICE} @$basedir/build/templates.sql > $basedir/build/templates.out
templatesLoaded=true
cd $basedir
PATH=$oldPATH
fi
read -p "Import database? (y/n) " response
response=${response,,}
if [[ $response =~ ^(yes|y| ) ]]; then
cd $basedir/src/game/server/database/build/linux
if [[ -z "$DBSERVICE" ]]; then
echo "Enter the DSN for the database connection "
read DBSERVICE
fi
if [[ -z "$DBUSERNAME" ]]; then
echo "Enter the database username "
read DBUSERNAME
fi
if [[ -z "$DBPASSWORD" ]]; then
echo "Enter the database password "
read DBPASSWORD
fi
./database_update.pl --username=$DBUSERNAME --password=$DBPASSWORD --service=$DBSERVICE --goldusername=$DBUSERNAME --loginusername=$DBUSERNAME --createnewcluster --packages
if [[ $templatesLoaded = false ]]; then
echo "Loading template list"
perl ../../templates/processTemplateList.pl < ../../../../../../dsrc/sku.0/sys.server/built/game/misc/object_template_crc_string_table.tab > $basedir/build/templates.sql
sqlplus ${DBUSERNAME}/${DBPASSWORD}@${DBSERVICE} @$basedir/build/templates.sql > $basedir/build/templates.out
fi
fi
echo "Build complete!"

134
sid_readme_priv.md Normal file
View File

@@ -0,0 +1,134 @@
# Debian SID SWGMasters Developer VM (PRIVATE REPO ONLY)
## Download
(not currently available)
### Special Notes for Image v6
If you're using version 6 of the development image, you'll need to do a few things prior to being able to start the server (but AFTER all other steps):
- Add the compiled binary locations to the PATH variable
```export PATH=$PATH:/home/swg/swg-main/build/bin```
- You'll also need to possibly edit the build_linux.sh script (located in the swg-main folder) and set the MODE equal to "Debug" instead of "Release". If you run into issues
starting the server for the first time, set to Debug, recompile the server, rebuild the templates (the compile script step below), truncate your OBJECT_TEMPLATES table and
re-import your database.
## System Requirements
* Virtualbox 5.0.x
* 4GB RAM minimum (The VM supports 64GB RAM)
* 30GB Harddisk Space
Recommended:
* SSH-Client (Putty in Windows)
* SCP-Client (WinSCP)
* more RAM if you want to run more then 1-2 Zones
* SSD as VM Storage
## What's Included In The VM
* Debian SID/Testing 32Bit
* OracleDB 11g Release 2
* Oracle Enterprise Manager https://<vmip>:1158/em/console (User: SYSTEM Pass: swg)
* Clientfiles needed to start the server /home/swg/clientdata/
* Appearance Files needed to start the server /home/swg/appearance/
* Copy of https://bitbucket.org/swgmasters/swg-src/ /home/swg/swg-src/
* All predependecies installed to compile your own server
* Samba preinstalled pointed to /home/swg/ (You can use editors/IDEs or/and your git in Windows)
* Dummy-X-Server to run X-Applications through VNC (Isnt started by default, google vnc4server)
Default Password: swg
## What Do You Need To Do To Get A Server Running?
Import the Appliance to Virtualbox.
* CPU Setting PAE
* Network Setting: Bridge Network
Change the /etc/hosts file to the right ipaddress.
nano /etc/hosts
Change the 192.168.2.113 to the IP of the Virtual Machine
<yourip> swg
Restart the server:
shutdown -r now
Download Putty and point it to the IP of your VM
Login as user swg with password swg
Delete the public repo (You can skip this, if you want to build both binarysets on the same system)
rm /home/swg/swg-src -rf
Create an ssh-key to use with the private gitlab as user swg
ssh-keygen -t rsa
Copy the public key to your gitlab account settings. (Profile Settings -> SSH-Keys)
cat /home/swg/.ssh/id_rsa.pub
After this you can download the private main repo:
cd /home/swg
git clone git@git.stellabellum.net:staff/swg-main.git
When you are done with the git clone part, go into the swg-main folder
cd /home/swg/swg-main
touch .setup
Start the Download of other Repos by using the build_linux.sh git pull/push option.
./build_linux.sh
!! Ignore the install dependencies PART !!
## Building Phases
Follow the instructions. The binary building phase will take roughly 1h/1Core.
The Script Building Phase will throw errors if you skip the configphase, do configs first, then scriptbuilding.
### Config Phase
use local
Database DSN:
//127.0.0.1/swg
Database User:
swg
Database Password:
swg
### Script Building
Scriptbuilding will take about 6hours the first time. You can later just recompile single scripts or tab files, look at the
utils/build_ and the build_linux.sh files to see the syntax of the mocha, javac and compilertools.
### Database
The Clustername has to be the same you used in the configphase. The same for the nodeip. The other settings are self-explaining.
## Clientdata and Appearance Files
The Clientdata Repo is copied from our Git here, its in /home/swg/clientdata. http://git.stellabellum.net/staff/clientdata
The .git Folder is removed to save space!
You need to modify:
* exe/shared/servercommon.cfg
[SharedFile]
searchPath2=../../data/sku.0/sys.shared/compiled/game
searchPath2=../../data/sku.0/sys.server/compiled/game
searchPath1=../../data/sku.0/sys.shared/built/game
searchPath1=../../data/sku.0/sys.server/built/game
searchPath0=../../data/sku.0/sys.client/compiled/clientdata
* mkdir /home/swg/swg-main/data/sku.0/sys.client/compiled
* ln -s /home/swg/clientdata /home/swg/swg-main/data/sku.0/sys.client/compiled/clientdata
## First Start
./startServer.sh
Point your login.cfg to the IP of the Virtualmachine.

25
startServer.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/bash
cd exe/linux
export LLVM_PROFILE_FILE="output-%p.profraw"
killall LoginServer &> /dev/null
killall CentralServer &> /dev/null
killall ChatServer &> /dev/null
killall CommoditiesServer &> /dev/null
killall ConnectionServer &> /dev/null
killall CustomerServiceServer &> /dev/null
killall LogServer &> /dev/null
killall MetricsServer &> /dev/null
killall PlanetServer &> /dev/null
killall ServerConsole &> /dev/null
killall SwgDatabaseServer &> /dev/null
killall SwgGameServer &> /dev/null
killall TransferServer &> /dev/null
./bin/LoginServer -- @servercommon.cfg &
sleep 5
./bin/TaskManager -- @servercommon.cfg

3
startWithLogging.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
bash startServer.sh |& tee output.log

BIN
tools/AddressToLine.exe Normal file

Binary file not shown.

146
tools/AutomatedDailyBuild.pl Executable file
View File

@@ -0,0 +1,146 @@
#!/usr/bin/perl -w
use File::Find;
use BuildFunctions;
###
# Copyright (C)2000-2002 Sony Online Entertainment Inc.
# All Rights Reserved
#
# Title: AutomatedDailyBuild.pl
# Description: Forces a sync to current, syncs to head, builds all_Client, SWGGameServer, PlanetServer, and SwgLoadServer and check for writable files in the src directory then emails log files to gmcdaniel.
# @author $Author: gmcdaniel $
# @version $Revision: #17 $
##
##
# This subroutine finds any non-authorized writable files in a passed directory
sub Find_Writable
{
if (-d $_)
{
# found a directory entry
# prune the directory if it's one we want to ignore
if (m/^(compile)$/)
{
#prune it
$File::Find::prune = 1;
}
}
elsif (-f and -w $_)
{ if (!m/^.*(aps|ncb|opt|plg)$/)
{
print "n $File::Find::name\n";
print Logfile "n $File::Find::name\n";
}
}
} # End of sub Find_Writable
########## MAIN ##########
##
# Delete compile directory for clean build
system("c:\\4nt302\\4nt /c del /s /y ..\\src\\compile");
#
## End of Delete compile directory for clean build
##
# Sync Code to Head
print ("Beginning Sync to Head...\n");
# sync client that points to d:\workdaily
system ("p4 -c gmcdaniel-wxp-gmcdaniel-build-station-machine_daily_build sync //depot/swg...\#head");
print ("Sync Complete\n");
print ("\n");
print ("\n");
#
## End of Sync Code to Head
##
# Forced Code
print ("Beginning Forced Sync...\n");
# sync client that points to d:\workdaily
system ("p4 -c gmcdaniel-wxp-gmcdaniel-build-station-machine_daily_build sync -f //depot/swg...\#have");
print ("Sync Complete\n");
print ("\n");
print ("\n");
#
## End of Forced Sync
##
# Build Projects and Check for Errors
build_project ("_all_client");
Check_For_Warnings_and_Errors("_all_client");
#build_project ("PlanetServer");
#Check_For_Warnings_and_Errors("PlanetServer");
#build_project ("SwgGameServer");
#Check_For_Warnings_and_Errors("SwgGameServer");
#build_project ("SwgLoadClient");
#Check_For_Warnings_and_Errors("SwgLoadClient");
#
## End of Build Projects and Check for Errors
##
# Check for any non-authorized writable files in the /swg/current/src directory and email the results
### Email addresses
#$gmcdaniel = "gmcdaniel\@soe.sony.com";
#$writable_files_log = "WritableFiles.log";
#print ("Checking for writable files...\n");
#open (Logfile, ">d:\\buildlogs\\$writable_files_log") || die "Sorry, I couldn't create $writable_files_log";
#print Logfile "The writable files that were found:\n";
# do a find
#$search_path = "..\\src";
#@ARGV = ($search_path);
#find(\&Find_Writable, @ARGV);
#close (Logfile);
#$writable_test_time_and_date = get_time_and_date();
#$date_stamp = get_date();
#system ("copy d:\\buildlogs\\$writable_files_log d:\\buildlogs\\WritableFiles_$writable_test_time_and_date.log");
#print ("Checking for writable files completed\n");
#print ("\n");
#print ("\n");
#system ("postie -host:sdt-mx1.station.sony.com -to:$gmcdaniel -from:$gmcdaniel -s:\"Writable Files Results $date_stamp\" -nomsg -file:d:\\buildlogs\\WritableFiles_$writable_test_time_and_date.log");
#
## End of Check for any non-authorized writable files in the /swg/current/src directory and email the results
########## END OF MAIN ##########

View File

@@ -0,0 +1,45 @@
#!/usr/bin/perl -w
########## MAIN ##########
##
#
print ("Synching to head\n");
system ("p4 sync \#head");
print ("End of sync to head\n");
print ("Cleaning process...\n");
system ("make -C ./work/swg/current/src/build/linux/ cleanall");
print ("Cleaning Process Complete\n");
print ("Starting Debug Server Build\n");
system ("make -C ./work/swg/current/src/build/linux/ debug 2>&1 | tee grant debug.log");
print ("Debug Server Build Complete\n");
print ("\n");
print ("Cleaning process...\n");
system ("make -C ./work/swg/current/src/build/linux/ cleanall");
print ("Cleaning Process Complete\n");
print ("Starting Release Server Build\n");
system ("make -C ./work/swg/current/src/build/linux/ release 2>&1 | tee grantrelease.log");
print ("Release Server Build Complete\n");
print ("Mailing debug log");
system ("mail -s \"[BUILDLOG] Daily Debug Server Log\" gmcdaniel\@soe.sony.com cmayer\@soe.sony.com asommers\@soe.sony.com jgrills\@soe.sony.com jbrack\@soe.sony.com <grantdebug.log");
print ("Mailing release log");
system ("mail -s \"[BUILDLOG] Daily Release Server Log\" gmcdaniel\@soe.sony.com cmayer\@soe.sony.com asommers\@soe.sony.com jgrills\@soe.sony.com jbrack\@soe.sony.com <grantrelease.log");
#
##
########## END OF MAIN ##########

View File

@@ -0,0 +1,13 @@
@echo off
dir /ba:d > dirs.txt
for ddd in (@dirs.txt) gosub dddd
del /e /z /q dirs.txt
quit 0
:dddd
echo %ddd
cd %ddd
call BuildIncludeHeaderFiles
cd ..
return

14
tools/BuildAllDsps.btm Normal file
View File

@@ -0,0 +1,14 @@
@echo off
set tmpFile=_allDsps.tmp
c:\cygwin\bin\find ../src -name "settings.rsp" > %tmpFile
perl -pi.bak -e"s/\/(\w*)\/build\/win32\/settings\.rsp/\/$1\/build\/win32\/$1\.dsp/g;" %tmpFile
cat %tmpFile
xargs p4 edit < %tmpFile
for %file in (@%tmpFile) do (echo Building %file & buildDsp.pl %file)
xargs p4 revert -a < %tmpFile
rm %tmpFile

3
tools/BuildAllVcproj.btm Normal file
View File

@@ -0,0 +1,3 @@
@echo off
perl buildAllVcproj.pl

View File

@@ -0,0 +1,44 @@
@echo off
if not exist "SwgClient_r.exe" goto error
set dd=%_date
set dn=patcher_20%@instr[6,2,%dd]%@instr[0,2,%dd]%@instr[3,2,%dd]beta
inkey Press ESC to abort creating patcher version %dn: %%key
if "%@ascii[%key]" == "27" goto :end
md \%dn
copy /u h:\gmcdaniel\public\patch_trees\*.tre \%dn
copy /u SwgClient_r.exe \%dn
copy /u dpvs.dll \%dn
copy /u dpvsd.dll \%dn
copy /u gl04_r.dll \%dn
copy /u dbghelp.dll \%dn
copy /u DllExport.dll \%dn
copy /u template_patcher_client.cfg \%dn\client.cfg
copy /u mss32.dll \%dn
md \%dn\miles
copy /u miles\*.* \%dn\miles\
goto end
:error
echo You must run this from the exe\win32 directory!
goto end
pushd /%dn
del \\sdlux2\projects\pc\patch\starwars\game\*.tre
copy /u *.* \\sdlux2\projects\pc\patch\starwars\game
popd
popd
start http://laser:7000
pause
:end

86
tools/BuildChanges.pl Executable file
View File

@@ -0,0 +1,86 @@
#!/usr/bin/perl
use strict;
use warnings;
sub usage
{
die "usage: $0 [-i] [-t] perforce_file_spec start_changelist end_changelist\n" .
"\t-i show internal notes\n" .
"\t-t show testplan\n";
}
my $showInternal = 0;
my $showTestplan = 0;
usage() if (@ARGV < 3);
while ($ARGV[0] eq "-i" || $ARGV[0] eq "-t")
{
$showInternal = 1 if ($ARGV[0] eq "-i");
$showTestplan = 1 if ($ARGV[0] eq "-t");
shift;
}
my $spec = shift;
my $first = shift;
my $last = shift;
open(P4, "p4 changes $spec\@$first,$last |");
my @changes = <P4>;
close(P4);
foreach (@changes)
{
chomp;
s/'.*//;
my $changeline = $_;
s/^Change //;
s/ .*//;
my $change = $_;
open(P4, "p4 describe -s $change |");
my $public = "";
my $internal = "";
my $testplan = "";
my $junk = "";
my $section = "junk";
while (<P4>)
{
if (s/^\t//)
{
if (/\[public\]/)
{
$section = "public";
}
elsif (/\[internal\]/)
{
$section = "internal";
}
elsif (/\[testplan\]/)
{
$section = "testplan";
}
elsif (/\[/)
{
$section = "junk";
}
elsif ($_ ne "\n")
{
$public .= $_ if ($section eq "public");
$internal .= $_ if ($section eq "internal");
$testplan .= $_ if ($section eq "testplan");
}
}
else
{
$section = "junk";
}
}
close(P4);
print $changeline,"\n" if ($public ne "" || ($showInternal && $internal ne "") || ($showTestplan && $testplan ne ""));
print "[public]\n", $public, "\n" if ($public ne "");
print "[internal]\n", $internal, "\n" if ($showInternal && $internal ne "");
print "[testplan]\n", $testplan, "\n" if ($showTestplan && $testplan ne "");
print "\n\n" if ($public ne "" || $internal ne "" || $testplan ne "");
}

1603
tools/BuildDsp.pl Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
cd ..\src\engine\shared\library
call BuildAllDirectoryIncludeHeaderFiles
cd ..\..\..\engine\client\library
call BuildAllDirectoryIncludeHeaderFiles
cd ..\..\..\engine\server\library
call BuildAllDirectoryIncludeHeaderFiles
cd ..\..\..\game\shared\library
call BuildAllDirectoryIncludeHeaderFiles
cd ..\..\..\game\client\library
call BuildAllDirectoryIncludeHeaderFiles
cd ..\..\..\..\tools

278
tools/BuildFunctions.pm Normal file
View File

@@ -0,0 +1,278 @@
package BuildFunctions;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(build_project Check_For_Warnings_and_Errors get_time_and_date get_date);
###
# Copyright (C)2000-2002 Sony Online Entertainment Inc.
# All Rights Reserved
#
# Title: BuildFunctions.pl
# Description: This file contains the various functions used by the different build scripts.
# @author $Author: gmcdaniel $
# @version $Revision: #1 $
##
#todo Possible failure points that I need to fix. The ResultsLogfile file can fail to be opened in one sub but still try to be written to in Check_Logfile_For_Warnings_and_Errors
#todo Bad coding to call ResultsLogFile without acutally passing it in to the sub? Probably
##
# This subroutine builds the passed project. It is passed the project name, the string for the project to build, and the project type (release or debug)
sub build
{
print ("Beginning $_[1] build...\n");
system("msdev ..\\src\\build\\win32\\swg.dsw /MAKE \"$_[1]\" /y3 /REBUILD /OUT d:\\buildlogs\\$_[0]_$_[2].log");
print ("$_[1] build complete\n");
print ("\n");
$timestamp = get_time_and_date();
$timeStamped_Log = $_[0]."_".$_[2]."_".$timestamp.".log";
system ("copy d:\\buildlogs\\$_[0]_$_[2].log d:\\buildlogs\\$timeStamped_Log");
print ("\n");
print ("\n");
} # End of sub build
##
# This subroutine calls the build subroutine to build both the release and debug versions of the project that is passed
sub build_project
{
$project = $_[0]." - Win32 Release";
$type = "Release";
build($_[0],$project,$type);
$project = $_[0]." - Win32 Debug";
$type = "Debug";
build($_[0],$project,$type);
$project = $_[0]." - Win32 Optimized";
$type = "Optimized";
build($_[0],$project,$type);
} # End of sub build_project
##
# This subroutine returns the current local time and date
sub get_time_and_date
{
($sec, $min, $hour, $day, $month, $year) = (localtime) [0,1,2,3,4,5];
$month = $month + 1;
$year = $year + 1900;
$dayandtime = $month."_".$day."_".$year."__".$hour."_".$min."_".$sec;
return $dayandtime;
} # End of sub get_time_and_date
##
# This subroutine returns the current local date
sub get_date
{
($day, $month, $year) = (localtime) [3,4,5];
$month = $month + 1;
$year = $year + 1900;
$date = $month."/".$day."/".$year;
return $date;
} # End of sub get_date
##
# This subroutine checks for warnings and errors in the build logs. If there is an error it returns true otherwise it returns false.
# It takes the name the logfile to check and the resulting exe or project name as input.
sub Check_Logfile_For_Warnings_and_Errors
{
$third_to_last_line = "test_line_3";
$second_to_last_line = "test_line_2";
open (Logfile,"d:\\buildlogs\\$_[0]") || die "Cannot open $_[0] for reading.";
while (<Logfile>)
{
chomp;
$third_to_last_line = $second_to_last_line;
$second_to_last_line = $_;
}
close (Logfile) || die "can't close $_[0]";
print ("\n");
print ("$third_to_last_line\n");
print ("$second_to_last_line\n");
print ResultsLogfile ("$third_to_last_line\n");
print ResultsLogfile ("$second_to_last_line\n");
print ResultsLogfile ("\n");
$search_for_errors= "0 error";
$search_for_warnings= "0 warning";
$match=-1;
#check for 0 errors.
if (index($third_to_last_line, $search_for_errors,$match) > -1) {
print ("No errors Found in $_[0]\n");
print ("\n");
#check for warnings
if (index($third_to_last_line, $search_for_warnings,$match) > -1) {
#no warnings or errors found
print ("No Warnings Found in $_[0]\n");
print ("\n");
return "false";
}
#a warning was found
print ("Warning Found in $_[0]\n");
print ("\n");
return "true";
}
#an error was found
else {
print ("Error Found in $_[0]\n");
print ("\n");
return "true";
}
} # End of sub Check_Logfile_For_Warnings_and_Errors
##
# This subroutine checks for warnings and errors in the build logs. If there is an error or warning it notifies QA and the lead programmers.
# If there is not an error or warning then the build log is just sent to QA.
# It takes the name of the project and the resulting exe or project name as input.
sub Check_For_Warnings_and_Errors
{
print ("Checking for errors and warnings...\n");
print ("\n");
# create file to store warnings and errors for inclusion in body of email.
open (ResultsLogfile, ">d:\\buildlogs\\$_[0]Results.log") || die "Sorry, I couldn't create $_[0]Results.log";
# Prints to results file for easier email formatting
print ResultsLogfile ("\n");
print ResultsLogfile ("Release Build:\n");
# Checks for errors or warnings in the release build
$Logfile_to_check = $_[0]."_Release.log";
$ReleaseError = Check_Logfile_For_Warnings_and_Errors($Logfile_to_check);
# Prints to results file for easier email formatting
print ResultsLogfile ("\n");
print ResultsLogfile ("Debug Build:\n");
# Checks for errors or warnings in the debug build
$Logfile_to_check = $_[0]."_Debug.log";
$DebugError = Check_Logfile_For_Warnings_and_Errors($Logfile_to_check);
# Prints to results file for easier email formatting
print ResultsLogfile ("\n");
print ResultsLogfile ("Optimized Build:\n");
# Checks for errors or warnings in the debug build
$Logfile_to_check = $_[0]."_Optimized.log";
$OptimizedError = Check_Logfile_For_Warnings_and_Errors($Logfile_to_check);
# Closes file used for the number of errors and warnings
close (ResultsLogfile);
# Email addresses
$gmcdaniel = "gmcdaniel\@soe.sony.com";
$jbrack = "jbrack\@soe.sony.com";
$jgrills = "jgrills\@soe.sony.com";
$asommers = "asommers\@soe.sony.com";
$cmayer = "cmayer\@soe.sony.com";
$prog_leads = "-to:$gmcdaniel -to:$jgrills -to:$cmayer -to:$asommers -cc:$jbrack";
$date_stamp = get_date();
if ($ReleaseError eq "true")
{
print ("Error or warning found in $_[0] Release Log. Emailing appropriate people.\n");
# Email the results to Programmer Leads and QA
system ("postie -host:sdt-mx1.station.sony.com $prog_leads -from:$gmcdaniel -s:\"[BUILDLOG] Errors or Warnings in Daily $_[0] Build Logs $date_stamp\" -nomsg -file:d:\\buildlogs\\$_[0]Results.log -a:d:\\buildlogs\\$_[0]_Release.log -a:d:\\buildlogs\\$_[0]_Debug.log -a:d:\\buildlogs\\$_[0]_Optimized.log");
}
elsif ($DebugError eq "true")
{
print ("Error or warning found in $_[0] Debug Log. Emailing appropriate people.\n");
# Email the results to Programmer Leads and QA
system ("postie -host:sdt-mx1.station.sony.com $prog_leads -from:$gmcdaniel -s:\"[BUILDLOG] Errors or Warnings in Daily $_[0] Build Logs $date_stamp\" -nomsg -file:d:\\buildlogs\\$_[0]Results.log -a:d:\\buildlogs\\$_[0]_Release.log -a:d:\\buildlogs\\$_[0]_Debug.log -a:d:\\buildlogs\\$_[0]_Optimized.log");
}
elsif ($OptimizedError eq "true")
{
print ("Error or warning found in $_[0] Optimized Log. Emailing appropriate people.\n");
# Email the results to Programmer Leads and QA
system ("postie -host:sdt-mx1.station.sony.com $prog_leads -from:$gmcdaniel -s:\"[BUILDLOG] Errors or Warnings in Daily $_[0] Build Logs $date_stamp\" -nomsg -file:d:\\buildlogs\\$_[0]Results.log -a:d:\\buildlogs\\$_[0]_Release.log -a:d:\\buildlogs\\$_[0]_Debug.log -a:d:\\buildlogs\\$_[0]_Optimized.log");
}
else
{
print ("No errors or warnings found in $_[0] logs.");
# Email the results to QA and Programmer Leads
system ("postie -host:sdt-mx1.station.sony.com $prog_leads -from:$gmcdaniel -s:\"[BUILDLOG] $_[0] Build Successful $date_stamp\" -nomsg -file:d:\\buildlogs\\$_[0]Results.log");
}
print ("End of errors and warning check for $_[0] logs.\n");
print ("\n");
} # End of sub Check_For_Warnings_and_Errors
1;

View File

@@ -0,0 +1,76 @@
@echo off
set includesub=%@word["\",-0,%@lfn[.]]
if NOT ISDIR include mkdir include
if NOT ISDIR include\public mkdir include\public
if NOT ISDIR include\private mkdir include\private
if NOT ISDIR include\public\%includesub mkdir include\public\%includesub
if NOT ISDIR include\private\%includesub mkdir include\private\%includesub
del /e /y /q include\public\%includesub
del /e /y /q include\private\%includesub
dir /sbfa:-d src\shared\*.h src\shared\*.def > shared.txt
for %header in (@shared.txt) gosub header
dir /sbfa:-d src\win32\*.h src\win32\*.def > win32.txt
for %header in (@win32.txt) gosub win32
dir /sbfa:-d src\linux\*.h src\linux\*.def > linux.txt
for %header in (@linux.txt) gosub linux
dir /sbfa:-a-d include\public\%dirname > platform.txt
dir /sbfa:-a-d include\private\%dirname >> platform.txt
for %header in (@platform.txt) gosub platform
del /q shared.txt
del /q win32.txt
del /q linux.txt
del /q platform.txt
quit 0
:setup
set filename=include\%export\%includesub\%@filename[%header]
set relative=%@replace[%@lfn[.]\,..\..\,%header]
set relative=%@replace[\,/,%relative]
return
:header
gosub export
gosub setup
echo #include "%relative" >> %filename
return
:win32
gosub export
gosub setup
echo #if defined(PLATFORM_WIN32) >> %filename
echo #include "%relative" >> %filename
attrib /q -a %filename
return
:linux
gosub export
gosub setup
set iftest=if
if EXIST %filename set iftest=elif
echo #%iftest defined(PLATFORM_LINUX) >> %filename
echo #include "%relative" >> %filename
attrib /q -a %filename
return
:platform
echo #else >> %header
echo #error unsupported platform >> %header
echo #endif >> %header
attrib /q +a %header
return
:export
set export=public
set exportHandle=%@fileopen[%header, read, t]
set exportRead="%@fileread[%exportHandle]"
if %@index[%exportRead,PRIVATE] != -1 set export=private
set exportClose=%@fileclose[%exportHandle]
return

View File

@@ -0,0 +1,50 @@
@echo off
if not exist "SwgClient_r.exe" goto error
set dd=%_date
set dn=patcher_20%@instr[6,2,%dd]%@instr[0,2,%dd]%@instr[3,2,%dd]internal
inkey Press ESC to abort creating patcher version %dn: %%key
if "%@ascii[%key]" == "27" goto :end
md \%dn
copy /u h:\gmcdaniel\public\patch_stuff\patch_trees\*.tre \%dn
copy /u SwgClient_r.exe \%dn
copy /u SwgClient_r.pdb \%dn
copy /u SwgClient_o.exe \%dn
copy /u SwgClient_o.pdb \%dn
copy /u SwgClientSetup_r.exe \%dn
copy /u dpvs.dll \%dn
copy /u dpvsd.dll \%dn
copy /u gl04_r.dll \%dn
copy /u gl04_o.dll \%dn
copy /u dbghelp.dll \%dn
copy /u DllExport.dll \%dn
copy /u template_patcher_client.cfg \%dn\client.cfg
copy /u locations.txt \%dn
copy /u mss32.dll \%dn
md \%dn\miles
copy /u miles\*.* \%dn\miles\
goto end
:error
echo You must run this from the exe\win32 directory!
goto end
pushd /%dn
del \\sdlux2\projects\pc\patch\starwars\game\*.tre
copy /u *.* \\sdlux2\projects\pc\patch\starwars\game
popd
popd
start http://laser:7000
pause
:end

View File

@@ -0,0 +1,68 @@
#!/usr/bin/perl
use warnings;
use strict;
sub numerically
{
$a <=> $b;
}
# check command line arguments
if (@ARGV < 2 || ($ARGV[0] =~ /^[-\/]/) || !($ARGV[0] =~ /tre$/i))
{
die "usage: $0 [treefile.tre] [changelist ...]\n";
}
my $tre = shift;
# process all changelists gathering up files for the TRE
print "Processing changelists\n";
my %file;
foreach my $changelist (sort numerically @ARGV)
{
print "\t$changelist\n";
open(P4, "p4 describe -s $changelist |");
while (<P4>)
{
chomp;
if (s%^\.\.\. //depot/swg/live/(data/sku.\d+/sys.(client|shared)/[^\/]+/[^\/]+)/%%)
{
my $prefix = $1;
s/#\d+ .*//;
$file{$_} = "../../$prefix/" . $_;
}
}
close(P4);
}
print"\n";
# generate the tree file response file
print "Generating response file\n";
my $rsp = $tre;
$rsp =~ s/tre$/rsp/i;
open(RSP, ">" . $rsp);
foreach (sort keys %file)
{
print "\t", $_, " @ ", $file{$_}, "\n";
print RSP $_, " @ ", $file{$_}, "\n";
}
close(RSP);
print"\n";
# build the tree file
print "Generating tree file\n";
open(TRE, "TreeFileBuilder -r $rsp $tre |");
print "\t", $_ while (<TRE>);
close(TRE);
print "\n";
# generate the md5sum for the file
print "Generating md5sum\n";
my $md5 = $tre;
$md5 =~ s/tre$/md5/i;
system("md5sum -b $tre > $md5");
open(MD5, $md5);
print "\t", $_ while (<MD5>);
close(MD5);

View File

@@ -0,0 +1,59 @@
@echo off
if not exist "SwgClient_r.exe" goto error
set dd=%_date
set dn=patcher_20%@instr[6,2,%dd]%@instr[0,2,%dd]%@instr[3,2,%dd]internal
inkey Press ESC to abort creating patcher version %dn: %%key
if "%@ascii[%key]" == "27" goto :end
md \%dn
del data_compressed_appearance.rsp
del data_compressed_shader.rsp
del data_compressed_other.rsp
del data_uncompressed.rsp
..\..\tools\TreeFileRspBuilder common.cfg
..\..\tools\TreeFileBuilder -r data_compressed_appearance.rsp \%dn\data_compressed_appearance.tre
..\..\tools\TreeFileBuilder -r data_compressed_shader.rsp \%dn\data_compressed_shader.tre
..\..\tools\TreeFileBuilder -r data_compressed_other.rsp \%dn\data_compressed_other.tre
..\..\tools\TreeFileBuilder -r data_uncompressed.rsp \%dn\data_uncompressed.tre
copy /u SwgClient_r.exe \%dn
copy /u SwgClient_r.pdb \%dn
copy /u SwgClient_o.exe \%dn
copy /u SwgClient_o.pdb \%dn
copy /u SwgClientSetup_r.exe \%dn
copy /u dpvs.dll \%dn
copy /u dpvsd.dll \%dn
copy /u gl04_r.dll \%dn
copy /u gl04_o.dll \%dn
copy /u dbghelp.dll \%dn
copy /u DllExport.dll \%dn
copy /u template_patcher_client.cfg \%dn\client.cfg
copy /u locations.txt \%dn
copy /u mss32.dll \%dn
md \%dn\miles
copy /u miles\*.* \%dn\miles\
goto end
:error
echo You must run this from the exe\win32 directory!
goto end
pushd /%dn
del \\sdlux2\projects\pc\patch\starwars\game\*.tre
copy /u *.* \\sdlux2\projects\pc\patch\starwars\game
popd
popd
start http://laser:7000
pause
:end

View File

@@ -0,0 +1,56 @@
@echo off
if not exist "common.cfg" goto error1
if "%1" == "" goto error2
timer
set dn=patcher_%1
inkey Press ESC to abort creating patcher version %dn: %%key
if "%@ascii[%key]" == "27" goto :end
md \%dn
if "%2" == "-t" gosub buildtrees
copy /u ..\..\src\compile\win32\SwgClient\Release\SwgClient_r.exe \%dn
copy /u ..\..\src\compile\win32\SwgClient\Release\SwgClient_r.pdb \%dn
copy /u ..\..\src\compile\win32\SwgClient\Optimized\SwgClient_o.exe \%dn
copy /u ..\..\src\compile\win32\SwgClient\Optimized\SwgClient_o.pdb \%dn
copy /u ..\..\src\compile\win32\SwgClientSetup\Release\SwgClientSetup_r.exe \%dn
copy /u ..\..\dev\win32\*.dll \%dn
copy /u template_patcher_client.cfg \%dn\client.cfg
copy /u locations.txt \%dn
copy /u mss32.dll \%dn
md \%dn\miles
copy /u miles\*.* \%dn\miles\
timer
goto end
:buildtrees
del data_compressed_animation.rsp
del data_compressed_mesh_skeletal.rsp
del data_compressed_mesh_static.rsp
del data_compressed_other.rsp
del data_compressed_texture.rsp
del data_uncompressed_music.rsp
del data_uncompressed_sample.rsp
..\..\tools\TreeFileRspBuilder common.cfg
..\..\tools\TreeFileBuilder -r data_compressed_animation.rsp \%dn\data_compressed_animation.tre
..\..\tools\TreeFileBuilder -r data_compressed_mesh_skeletal.rsp \%dn\data_compressed_mesh_skeletal.tre
..\..\tools\TreeFileBuilder -r data_compressed_mesh_static.rsp \%dn\data_compressed_mesh_static.tre
..\..\tools\TreeFileBuilder -r data_compressed_other.rsp \%dn\data_compressed_other.tre
..\..\tools\TreeFileBuilder -r data_compressed_texture.rsp \%dn\data_compressed_texture.tre
..\..\tools\TreeFileBuilder -r data_uncompressed_music.rsp -f \%dn\data_uncompressed_music.tre
..\..\tools\TreeFileBuilder -r data_uncompressed_sample.rsp -f \%dn\data_uncompressed_sample.tre
return
:error1
echo You must run this from the exe\win32 directory!
goto end
:error2
echo Usage: BuildTreeFileVersion changelist [-t (build tree files)]
:end

2553
tools/BuildVcproj.pl Executable file

File diff suppressed because it is too large Load Diff

240
tools/CheckPatchTreeSize.pl Executable file
View File

@@ -0,0 +1,240 @@
#! /usr/bin/perl
# ======================================================================
# ======================================================================
use strict;
use warnings;
use File::Copy;
# ======================================================================
# Globals
# ======================================================================
my $oldManifest = "dailyPatchSizeOld.mft";
my $newManifest = "dailyPatchSizeNew.mft";
my $tabFile = "CheckPatchTreeSize.tab";
my $numberOfTabOuts = 15;
my $p4 = "p4";
my $branch;
my $changelist;
my $toolsDir;
my %patchTreeSizes;
my $name = $0;
$name =~ s/^(.*)\\//;
my $logfile = $name;
$logfile =~ s/\.pl$/\.log/;
# ======================================================================
# Subroutines
# ======================================================================
sub getP4dir
{
my $path = $_[0];
open(P4, "p4 where ${path}... |");
my $perforceDir;
while(<P4>)
{
$perforceDir = $_;
}
my @temp = split /\s+/, $perforceDir;
my $retDir = $temp[2];
close(P4);
$retDir =~ s/\.\.\.//g;
return $retDir;
}
sub usage
{
die "\n\t$name <input manifest> <branch> [<changelist>]\n\n";
}
sub readMft
{
my ($filename, $hashRef) = @_;
return if (!-e $filename);
open(MFT, $filename);
my $version = <MFT>;
chomp $version;
$version =~ s/ .*//;
die "unsupported manifest version" if ($version ne "version2");
while(<MFT>)
{
my ($archive, $action, $uncsize, $cmpsize, $checksum, $depotfile, $file) = /^(\S+)\t\S+\t(\S+)\t\S+\t(\S+)\t(\S+)\t(\S+)\t(\S+)\#\d+\t(\S+)\n$/;
next if(!defined $file);
$$hashRef{$depotfile} = [$checksum, $file, $archive, $action, $uncsize, $cmpsize];
}
close(MFT);
}
sub doSync
{
my $oldchangelist = -1;
open(TABFILE, $tabFile) || goto NOTABFILE;
while(<TABFILE>)
{
$oldchangelist = $1 if(/(\d+)\n/);
}
close(TABFILE);
NOTABFILE:
if($oldchangelist == -1)
{
system("$p4 sync //depot/swg/$branch/data/...\@$changelist //depot/swg/$branch/exe/win32/...\@$changelist > $logfile 2>&1");
}
else
{
system("$p4 sync //depot/swg/$branch/data/...\@$oldchangelist,$changelist //depot/swg/$branch/exe/win32/...\@$changelist > $logfile 2>&1");
}
}
sub doExcelOut
{
my @tabOuts;
print "\nTab delimeted output for $branch:\n";
my @skus = (sort keys %patchTreeSizes);
print "Time\t";
foreach (@skus)
{
print "sku.$_\t";
}
print "Changelist\n";
if (-e $tabFile)
{
open(TABFILE, $tabFile);
while(<TABFILE>)
{
push @tabOuts, $_;
}
close(TABFILE);
}
while(@tabOuts > $numberOfTabOuts)
{
shift @tabOuts;
}
foreach (@tabOuts)
{
print;
}
my ($sec, $min, $hr, $day, $mon, $yr) = localtime time;
my $timestamp = sprintf "%4s-%02s-%02s %02s:%02s:%02s", ($yr + 1900), ($mon + 1), $day, $hr, $min, $sec;
my $output = "$timestamp\t";
foreach (@skus)
{
if(exists $patchTreeSizes{$_})
{
$output .= "$patchTreeSizes{$_}\t";
}
else
{
$output .= "0\t";
}
}
$output .= "$changelist\n";
print $output;
open(TABFILE, ">>$tabFile");
print TABFILE $output;
close(TABFILE);
}
sub doChanges
{
my %oldMft;
my %newMft;
my @output;
# Read in the mft file information
readMft($oldManifest, \%oldMft);
readMft($newManifest, \%newMft);
# Check for differences
foreach (keys %newMft)
{
# Only update output if the file is new, or the checksum has changed
next if(exists $oldMft{$_} && $newMft{$_}->[0] eq $oldMft{$_}->[0]);
my $uncDiff = $newMft{$_}->[4] - ((exists $oldMft{$_}) ? $oldMft{$_}->[4] : 0);
my $cmpDiff = $newMft{$_}->[5] - ((exists $oldMft{$_}) ? $oldMft{$_}->[5] : 0);
push @output, join("\t", $_, $newMft{$_}->[1], $newMft{$_}->[2], $newMft{$_}->[3], $uncDiff, $cmpDiff);
}
print "\nFiles changed for $branch:\n";
print join("\t", "Depot Name", "File Name", "Archive", "Action", "Size Added (Uncompressed)", "Size Added (Compressed)"), "\n";
@output = sort { $a cmp $b } @output;
print join "\n", @output;
}
# ======================================================================
# Main
# ======================================================================
usage() if(@ARGV < 2);
my $inputManifest = shift;
$branch = shift;
$changelist = `p4 counter change`;
chomp $changelist;
$changelist = shift if (@ARGV);
$toolsDir = getP4dir("//depot/swg/current/tools/");
my $buildClientDataTreeFiles = getP4dir("//depot/swg/all/tools/build/shared/buildClientDataTreeFiles.pl");
my $exeDir = getP4dir("//depot/swg/$branch/exe/win32/");
chdir $exeDir or die "Could not change directory: $!";
my $pwd = `pwd`;
chomp $pwd;
$ENV{"PWD"} = $pwd;
doSync();
system("perl $buildClientDataTreeFiles --noVerify $newManifest $inputManifest 0 > $logfile");
die "Error creating patch tree - patch_0_00.tre does not exist\n" if(!-e "patch_0_00.tre");
opendir DH, $exeDir;
foreach (sort readdir DH)
{
if(/patch_sku([^_]+)_0_(\d+)\.tre/)
{
$patchTreeSizes{$1} = 0 if (!exists $patchTreeSizes{$1});
$patchTreeSizes{$1} += (-s $_);
}
elsif (/patch_0_(\d+)\.tre/)
{
$patchTreeSizes{0} = 0 if (!exists $patchTreeSizes{0});
$patchTreeSizes{0} += (-s $_);
}
}
closedir DH;
print "Patch tree sizes for $branch:\n";
foreach (sort keys %patchTreeSizes)
{
print "Size of sku$_.tre is: ".$patchTreeSizes{$_}."\n";
}
doExcelOut();
doChanges() if(-e $oldManifest);
move $newManifest, $oldManifest || die "move from $newManifest to $oldManifest failed";

Binary file not shown.

195
tools/ContentSync.pl Executable file
View File

@@ -0,0 +1,195 @@
#! /usr/bin/perl
#
# Fix for Malformed UTF-8 Character error in perl 5.8.0 on linux - "export LANG=en_US"
use warnings;
use strict;
# ======================================================================
# initialization
# setup perforce access environment variables
my $p4 = "p4";
my $branch = "";
my $startingChangelist = 0;
my $endingChangelist;
my $contentLevel = 2;
my $name = $0;
$name =~ s/^(.*)\\//;
my $logfile = $name;
$logfile =~ s/\.pl$/\.log/;
my $programmer = 0;
my $designer = 1;
my $artist = 2;
my $default = $programmer;
my %content;
# ======================================================================
sub usage
{
print STDERR "\nUsage:\n";
print STDERR "\t$name <branch> <starting changelist> <ending changelist>\n";
print STDERR "\n\tending changelist can be a changelist or #head\n";
die "\n";
}
sub getUsers
{
my ($group, $value) = @_;
my $foundUsers = 0;
open(P4, "$p4 group -o $group |");
while(<P4>)
{
$foundUsers = 1 if(/^Users:/);
next if(!$foundUsers);
$content{$1} = $value if(/^\s+(\S+)/);
}
close(P4);
}
# ======================================================================
&usage() if(@ARGV == 0);
my $forceContentLevel;
if(@ARGV == 4)
{
$forceContentLevel = shift @ARGV;
}
&usage() if(@ARGV != 3);
$branch = shift;
$startingChangelist = shift;
$endingChangelist = shift;
my $user;
print "Gathering list of users...\n";
getUsers("swg_programmers", $programmer);
getUsers("swg_leads", $programmer);
getUsers("swg_qa", $programmer);
getUsers("swg_designers", $designer);
getUsers("swg_artists", $artist);
if (defined $forceContentLevel)
{
$contentLevel = $forceContentLevel;
$user = "ContentLevelOverride";
}
else
{
open(P4, "$p4 user -o |") || die "p4 user failed\n";
while(<P4>)
{
if(/^User:\s+(\S+)/)
{
$user = $1;
die "Could not determine if $user is a programmer, designer, or artist\n" if(!exists $content{$user});
$contentLevel = $content{$user};
}
}
close(P4);
}
my $level;
die "Unknown contentLevel: $contentLevel\n" if($contentLevel < 0);
$level = "programmer" if($contentLevel == 0);
$level = "designer" if($contentLevel == 1);
$level = "artist" if($contentLevel == 2);
$level = "specified content only" if($contentLevel >= 3);
print STDERR "Syncing for $user at content level of $level\n";
print STDERR "Getting changes from $startingChangelist to $endingChangelist...\n";
my @changes;
open(P4, "$p4 changes -s submitted //depot/swg/$branch/...\@$startingChangelist,$endingChangelist |") || die "p4 changes failed\n";
while (<P4>)
{
chomp;
s/^Change //;
s/ .*//;
unshift @changes, $_;
}
close(P4);
print STDERR "Scanning changes...\n";
# process all the changelists looking for content files
my %sync;
foreach my $changeList (@changes)
{
# read the change description
my $content = 0;
my $user;
my $notes = "";
my $file;
open(P4, "$p4 -ztag describe -s $changeList |") || die "die: p4 change failed";
while (<P4>)
{
# make the initial decision based on the user
if (/^\.\.\.\s+user\s+(.*)/)
{
$user = $1;
if (!defined $content{$user})
{
# If we don't have the user listed, use default
$content = $default >= $contentLevel ? 1 : 0;
print STDERR "could not determine content status of $1 for changelist $changeList\n";
}
else
{
$content = $content{$user} >= $contentLevel ? 1 : 0;
}
}
# allow overrides in the descriptions
if (/\[\s*no\s+content\s*\]/i)
{
$content = 0;
$notes = " specified [no content]";
}
if (/\[\s*content\s*\]/i)
{
$content = 1;
$notes = " specified [content]";
}
# remember content files
if ($content)
{
$file = $1 if (/^\.\.\.\s+depotFile\d+\s+(.*)/);
$sync{$file} = $1 if (/^\.\.\.\s+rev\d+\s+(.*)/);
}
}
# give summary of this changelist
print "no " if (!$content);
print "content $changeList $user$notes\n";
close(P4);
}
if (scalar(keys %sync) != 0)
{
print STDERR "\nUpdating the client with ", scalar(keys %sync), " file(s)...\n";
open(P4, "| $p4 -x - sync > $logfile 2>&1");
foreach (sort keys %sync)
{
print P4 $_, "#", $sync{$_}, "\n";
}
close(P4);
}
else
{
print STDERR "No files to update.\n";
}
#unlink($logfile);

BIN
tools/CoreMemWalker Normal file

Binary file not shown.

177
tools/CoreMemWalker.cpp Normal file
View File

@@ -0,0 +1,177 @@
// Compile this with g++ -O6 -o CoreMemWalker CoreMemWalker.cpp -static
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <cstdio>
#include <cstdlib>
// ======================================================================
struct SystemAllocation
{
int size;
unsigned int next;
int pad1, pad2;
};
struct AllocatedBlock
{
// Block is 16 for debug build, 12 for release build (release build doesn't have array)
unsigned int prev, next;
bool free:1;
#ifdef _DEBUG
bool array:1;
#endif
bool leakTest:1;
unsigned int size:30;
// AllocatedBlock starts here
unsigned int owner[64];
};
struct AddressOffset
{
unsigned int s, e, o;
};
// ======================================================================
int ao_c = 0;
AddressOffset ao[1024];
char const *coreMem = 0;
unsigned int coreLen = 0;
const unsigned int MAX_MAP_SIZE = 2000000000;
// ======================================================================
bool mapCore(char const *coreName)
{
int fd = open(coreName, O_RDONLY);
if (fd != -1)
{
struct stat s;
fstat(fd, &s);
coreLen = s.st_size;
if (coreLen > MAX_MAP_SIZE)
coreLen = MAX_MAP_SIZE;
coreMem = reinterpret_cast<char const *>(mmap(0, coreLen, PROT_READ, MAP_PRIVATE|MAP_NORESERVE, fd, 0));
close(fd);
}
return coreMem && coreMem != ((char const *)MAP_FAILED) ? true : false;
}
// ----------------------------------------------------------------------
void unmapCore()
{
if (coreMem)
munmap(reinterpret_cast<void *>(const_cast<char *>(coreMem)), coreLen);
}
// ----------------------------------------------------------------------
bool loadMemoryMap(char const *mapName)
{
FILE *fp = fopen(mapName, "r");
if (fp)
{
unsigned int a, c, d, e, f;
char b[512], g[512];
while (fscanf(fp, "%d %s %x %x %x %x %s\n", &a, b, &c, &d, &e, &f, g) == 7)
{
ao[ao_c].s = d;
ao[ao_c].e = d+c;
ao[ao_c].o = f-d;
++ao_c;
}
fclose(fp);
return true;
}
return false;
}
// ----------------------------------------------------------------------
char const *getMem(unsigned int addr)
{
for (int i = 0; i < ao_c; ++i)
if (addr >= ao[i].s && addr < ao[i].e)
return coreMem+addr+ao[i].o;
return coreMem;
}
// ----------------------------------------------------------------------
int main(int argc, char **argv)
{
if (argc != 5)
{
fprintf(stderr,
"Usage: CoreMemWalker coreName mapName firstSystemAllocationAddr ownerCount\n"
" This is only meant to be used from the coreMemReport.sh script.\n");
AllocatedBlock a;
fprintf(stderr, "sizeof(AllocatedBlock)=%d, sizeof(AllocatedBlock) - owner=%d\n", sizeof(AllocatedBlock), sizeof(AllocatedBlock) - sizeof(a.owner));
fprintf(stderr, "&AllocatedBlock=%p, sizeof=%d\n", &a, sizeof(a));
fprintf(stderr, "&AllocatedBlock.prev=%p, sizeof=%d\n", &a.prev, sizeof(a.prev));
fprintf(stderr, "&AllocatedBlock.next=%p, sizeof=%d\n", &a.next, sizeof(a.next));
fprintf(stderr, "&AllocatedBlock.owner=%p, sizeof=%d\n", &a.owner, sizeof(a.owner));
return 1;
}
char const *coreName = argv[1];
char const *mapName = argv[2];
unsigned int firstSystemAllocationAddr = atoi(argv[3]);
unsigned int ownerCount = atoi(argv[4]);
// int count = 0;
if ( mapCore(coreName)
&& loadMemoryMap(mapName))
{
unsigned int systemAllocationAddr = firstSystemAllocationAddr;
while (systemAllocationAddr)
{
SystemAllocation const * const systemAllocation = reinterpret_cast<SystemAllocation const *>(getMem(systemAllocationAddr));
AllocatedBlock const * const firstBlockForSA = reinterpret_cast<AllocatedBlock const *>(reinterpret_cast<char const *>(systemAllocation)+16);
AllocatedBlock const * const lastBlockForSA = reinterpret_cast<AllocatedBlock const *>(reinterpret_cast<char const *>(systemAllocation)+systemAllocation->size-16);
unsigned int blockAddr = firstBlockForSA->next;
AllocatedBlock const *block = reinterpret_cast<AllocatedBlock const *>(getMem(blockAddr));
while (block != lastBlockForSA)
{
if (!block->free)
{
printf("0x%x %d", blockAddr, block->size);
for (int i = 0; i < ownerCount; ++i)
printf(" 0x%x", block->owner[i]);
printf("\n");
// ++count;
// printf("%d\n", count);
// if (count > 2153024)
// break;
}
if (blockAddr == block->next)
break;
blockAddr = block->next;
block = reinterpret_cast<AllocatedBlock const *>(getMem(blockAddr));
}
// if (count > 2153024)
// break;
if (systemAllocationAddr == systemAllocation->next)
break;
systemAllocationAddr = systemAllocation->next;
}
unmapCore();
}
return 0;
}

BIN
tools/CoreMemWalker_debug Normal file

Binary file not shown.

Binary file not shown.

BIN
tools/Delta2.exe Normal file

Binary file not shown.

BIN
tools/ExtractProfileInfo Normal file

Binary file not shown.

View File

@@ -0,0 +1,70 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv)
{
if (argc != 2)
{
printf("syntax: \"%s search_string\"\n", argv[0]);
printf("example: \"%s SwgGameServer:15433 < profile.txt > chilastra_profile_restuss.txt\"\n", argv[0]);
printf("example: \"%s handleFX < profile.txt > handleFX_profile.txt\"\n", argv[0]);
return 0;
}
char * buffer[32768];
for (int i = 0; i < 32768; ++i)
buffer[i] = reinterpret_cast<char*>(malloc(512));
bool found = false;
int bufferIndex = 0;
while (gets(buffer[bufferIndex]))
{
if (strstr(buffer[bufferIndex], argv[1]))
{
found = true;
}
if (strlen(buffer[bufferIndex]) > 0)
{
++bufferIndex;
}
else
{
if (found)
{
for (int i = 0; i < bufferIndex; ++i)
{
printf("%s\n", buffer[i]);
}
printf("\n");
}
found = false;
bufferIndex = 0;
}
if (bufferIndex >= 32768)
{
printf("ERROR! Profile block exceeds 32768 lines\n");
found = false;
break;
}
}
if (found)
{
for (int i = 0; i < bufferIndex; ++i)
{
printf("%s\n", buffer[i]);
}
printf("\n");
}
for (int i = 0; i < 32768; ++i)
free(buffer[i]);
return 0;
}

BIN
tools/LINT-NT.EXE Normal file

Binary file not shown.

BIN
tools/LabelHashTool Normal file

Binary file not shown.

BIN
tools/LabelHashTool.exe Normal file

Binary file not shown.

363
tools/MoneyCheckActivity.pl Executable file
View File

@@ -0,0 +1,363 @@
#! /usr/bin/perl
use strict;
use warnings;
use Getopt::Std;
use Math::BigInt;
my %player_hash;
# key (player id) => (# trans to, total amt to them, last time to them,
# # trans from, total amt from them, last time from them)
# money_hash is a global hash referece for whatever player we are analyzing
my $money_hash;
my $cnt = 0;
my $sort_val = 0;
my $max_cnt = 0;
my %args;
my $start_time;
my $min_thresh = 0;
my $max_thresh = 0;
my $player_id = 0;
my $start_date;
my $end_date;
my $num_days;
my $total_in = new Math::BigInt '0';
my $total_out = new Math::BigInt '0';
my $num_total_in = new Math::BigInt '0';
my $num_total_out = new Math::BigInt '0';
my @keys;
my $big_zero = new Math::BigInt '0';
my $str_out;
my $abridged = 1;
# Usage
sub usage
{
my $name = $0;
$name =~ s/^(.*)\\//;
print STDERR "\nUsage:\n";
print STDERR "\t$name <optional parameters> <server> <start date> <end date> <player id> ... (as many player ids as you want to scan)\n";
print STDERR "\t\tDate format = yyyy-mm-dd (eg: 2004-06-08)\n";
print STDERR "\t$name <optional parameters> -f <money log file> <player id> ... (as many player ids as you want to scan)\n";
print STDERR "Optional parameters:\n";
print STDERR "\t[-l <num>] [-s <str> | -S <str>] [-n | -a | -t | -N | -A | -T] [-m <str> | -x <str> | -e <str>] [-d]\n";
print STDERR "\t-l <num>\tOnly process <num> lines of log file\n";
print STDERR "\t-s <time>\tStart processing at <time> \(eg \"2004-06-01 17:00:03\"\)\n";
print STDERR "\t-S <time>\tEnd processing at <time>\n";
print STDERR "\t-p \tSort by player id number (default)\n";
print STDERR "\t-n \tSort by number of transactions to the player\n";
print STDERR "\t-a \tSort by total amount of money to the player\n";
print STDERR "\t-t \tSort by time of most recent transaction to the player\n";
print STDERR "\t-N \tSort by number of transactions from the player\n";
print STDERR "\t-A \tSort by total amount of money from the player\n";
print STDERR "\t-T \tSort by time of most recent transaction from the player\n";
print STDERR "\t-m <str>\tSet minimum threshold for sorted parameter\n";
print STDERR "\t-x <str>\tSet maximum threshold for sorted parameter\n";
print STDERR "\t-e <str>\tSet threshold to exactly <num>\n";
print STDERR "\t-d \tShow detailed output\n";
die "\n";
}
# Adds money / player id into hash
# Two arguments - key, amount of money, and (to / from)
sub put_into
{
my ($key, $amt, $tim, $tf) = @_;
$tf = ($tf * 3);
$$money_hash{$key} = [0, 0, 0, 0, 0, 0, 0] if(!exists $$money_hash{$key});
$$money_hash{$key}->[$tf] += 1;
$$money_hash{$key}->[$tf+1] += $amt;
$$money_hash{$key}->[$tf+2] = $tim if($tim gt $$money_hash{$key}->[$tf+2]);
}
# Will sort numbers and strings - returns -1, 0, or 1
# Takes two arguments, to compare
sub str_num_cmp
{
my($a, $b) = @_;
# Both are numbers
return $a <=> $b if($a =~ /^\d+$/ && $b =~ /^\d+$/);
# Both are not numbers
return $a cmp $b if(!($a =~ /^\d+$/) && !($b =~ /^\d+$/));
# $a is a number, $b is not
return 1 if($a =~ /^\d+$/);
# $a is not a number, $ b is
return -1;
}
# Displays the money chart in %money_hash
# Takes no arguments
sub display_money_chart
{
my $temp_total = $big_zero;
my $temp_hash = $_[0];
my @key_vals;
my @sorted_vals;
@key_vals = keys %$money_hash;
@sorted_vals = ();
foreach my $sub_elem (@key_vals)
{
push(@sorted_vals, [$sub_elem, $$money_hash{$sub_elem}->[0], $$money_hash{$sub_elem}->[1],
$$money_hash{$sub_elem}->[2], $$money_hash{$sub_elem}->[3],
$$money_hash{$sub_elem}->[4], $$money_hash{$sub_elem}->[5]]);
}
@sorted_vals = sort { &str_num_cmp($b->[$sort_val], $a->[$sort_val]) } @sorted_vals;
@sorted_vals = reverse(@sorted_vals) if($sort_val == 0);
foreach my $val (@sorted_vals)
{
if((!exists $args{"m"} || (&str_num_cmp($val->[$sort_val], $min_thresh) == 0 || &str_num_cmp($val->[$sort_val], $min_thresh) == 1))
&& (!exists $args{"x"} || (&str_num_cmp($val->[$sort_val], $max_thresh) == 0 || &str_num_cmp($val->[$sort_val], $max_thresh) == -1))
&& (!exists $args{"e"} || &str_num_cmp($val->[$sort_val], $max_thresh) == 0))
{
$total_in += $val->[5];
$total_out += $val->[2];
$num_total_in += $val->[4];
$num_total_out += $val->[1];
if(!$abridged)
{
printf "\t%-34s%-8s%-12s%-24s%-8s%-12s%-24s\n", $val->[0], $val->[1], $val->[2], $val->[3], $val->[4], $val->[5], $val->[6];
}
else
{
$str_out = sprintf "%s\t%s\t%s\t%s\t%s\t%s\n", $val->[5], $val->[4], $val->[2], $val->[1], ($val->[5] - $val->[2]), $val->[0];
$str_out =~ s/\+//g;
print $str_out;
}
}
}
}
$start_time = time;
&usage() if(!getopts('dpnatNATm:x:l:e:s:S:f:', \%args));
&usage if(((exists $args{"n"}) + (exists $args{"a"}) + (exists $args{"t"})
+ (exists $args{"N"}) + (exists $args{"A"}) + (exists $args{"T"}) + (exists $args{"p"})) > 1);
&usage if((exists $args{"e"}) && (exists $args{"m"} || exists $args{"x"}));
# Process arguments
$sort_val = 0 if(exists $args{"p"});
$sort_val = 1 if(exists $args{"n"});
$sort_val = 2 if(exists $args{"a"});
$sort_val = 3 if(exists $args{"t"});
$sort_val = 4 if(exists $args{"N"});
$sort_val = 5 if(exists $args{"A"});
$sort_val = 6 if(exists $args{"T"});
$max_cnt = $args{"l"} if(exists($args{"l"}));
$min_thresh = $args{"m"} if(exists($args{"m"}));
$max_thresh = $args{"x"} if(exists($args{"x"}));
$min_thresh = $max_thresh = $args{"e"} if(exists($args{"e"}));
$start_date = $args{"s"} if(exists($args{"s"}));
$end_date = $args{"S"} if(exists($args{"S"}));
$abridged = 0 if(exists($args{"d"}));
if(exists($args{"f"}))
{
&usage if(@ARGV < 1);
open (MONEY, $args{"f"});
}
else
{
&usage if(@ARGV < 4);
my $server = shift;
my $start = shift;
my $end = shift;
open(MONEY, "/m2/logsrv/log_dump.pl swg money $server $start $end |");
}
# Fill the player hash
foreach(@ARGV)
{
$player_hash{$_} = {};
}
while (<MONEY>)
{
# Clear out three possible Unicode chars
s/^...20(\d{2})/20$1/;
chomp;
my $day;
my $time;
my $planet;
my $vara;
my $varb;
my $varc;
my $type;
my $from;
my $to;
my $amount;
my $total;
# Check start date if argument was passed
if(exists $args{"s"} && /^(\S+)\s+(\S+)/)
{
my $date = $1." ".$2;
next if($date lt $start_date);
}
# Check end date if argument was passed
if(exists $args{"S"} && /^(\S+)\s+(\S+)/)
{
my $date = $1." ".$2;
last if($date gt $end_date);
}
# Check a few special cases
if(/^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.+) (from|to) bank by (.+), amount (\d+), (total|total\(from\)) -?(\d+):$/)
{
#player deposited / withdrew money from bank
$day = $1;
$time = $2;
$planet = $3;
$vara = $4;
$varb = $5;
$varc = $6;
$type = $7;
$from = $8;
$to = $9;
$amount = $10;
$total = $11;
#Strip the station id - can cause problems searching for player id
$from =~ s/StationId\(\d+\)//g;
$to =~ s/StationId\(\d+\)//g;
# If it's a named account, strip the name out
$to =~ s/named account //;
# Extract player Id number
$to =~ s/.*\((\d+)\).*/$1/ if($to =~ /Player/);
# Add into the approproiate hash
if($from eq "to" && exists $player_hash{$to})
{
$money_hash = $player_hash{$to};
&put_into("bank", $amount, ($day." ".$time), 0);
}
if($to eq "from" && exists $player_hash{$to})
{
$money_hash = $player_hash{$to};
&put_into("bank", $amount, ($day." ".$time), 1);
}
}
elsif(/logging out with/ || /logged in with/)
{
#player logged in / out
next;
}
elsif(/^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.+) from (.+) to (.+), amount (\d+), (total|total\(from\)) -?(\d+):$/)
{
$day = $1;
$time = $2;
$planet = $3;
$vara = $4;
$varb = $5;
$varc = $6;
$type = $7;
$from = $8;
$to = $9;
$amount = $10;
$total = $11;
#Strip the station id - can cause problems searching for player id
$from =~ s/StationId\(\d+\)//g;
$to =~ s/StationId\(\d+\)//g;
# If it's a named account, strip the name out
$from =~ s/named account //;
$to =~ s/named account //;
# Extract player Id number
$from =~ s/.*\((\d+)\).*/$1/ if($from =~ /Player/);
$to =~ s/.*\((\d+)\).*/$1/ if($to =~ /Player/);
# Special case where player has " from " in store title
if($type =~ /Player/)
{
$type =~ s/(.*) from /$1/;
$from =~ s/.*\((\d+)\).*/$1/;
}
# Add into the approproiate hash
if(exists $player_hash{$from})
{
$money_hash = $player_hash{$from};
&put_into($to, $amount, ($day." ".$time), 0);
}
if(exists $player_hash{$to})
{
$money_hash = $player_hash{$to};
&put_into($from, $amount, ($day." ".$time), 1);
}
}
else
{
print "$_\n";
die "Error in log file format.\n";
}
# Check counter
++$cnt;
last if($cnt == $max_cnt);
}
close (MONEY);
#update money hash
foreach my $player (keys %player_hash)
{
$money_hash = $player_hash{$player};
$total_in = $big_zero;
$total_out = $big_zero;
$num_total_in = $big_zero;
$num_total_out = $big_zero;
if(!$abridged)
{
print "Transactions for user $player_id:\n";
print "---------------------------------\n\n";
print "\tTransactions:\n";
printf "\t%-34s%-8s%-12s%-24s%-8s%-12s%-24s\n", "Player Id:", "# To:", "Amt To:", "Last Tm To", "# Fr:", "Amt Fr:", "Last Tm Fr";
printf "\t%-34s%-8s%-12s%-24s%-8s%-12s%-24s\n", "----------", "-----", "-------", "----------", "-----", "-------", "----------";
display_money_chart();
print "\n";
print "Total money given to $player_id: $total_in\n";
print "Total money $player_id gave: $total_out\n";
print "\nFinished in ".(time - $start_time)." seconds.\n";
}
else
{
print "Information for player id: $player\n";
printf "%s\t%s\t%s\t%s\t%s\t%s\n", "To:", "# To:", "From:", "# From", "Delta:", "Account:";
display_money_chart();
$str_out = sprintf "\n%s\t%s\t%s\t%s\t%s\t%s\n", $total_in, $num_total_in, $total_out, $num_total_out, ($total_in - $total_out), "Total";
$str_out =~ s/\+//g;
print $str_out;
}
print "\n";
}

339
tools/MoneyNamedAccountToFrom.pl Executable file
View File

@@ -0,0 +1,339 @@
#! /usr/bin/perl
use strict;
use warnings;
use Getopt::Std;
use Math::BigInt;
my %from_hash;
my %to_hash;
my $cnt = 0;
my $sort_val = 0;
my $max_cnt = 0;
my %args;
my $start_time;
my $min_thresh = 0;
my $max_thresh = 0;
my $start_date;
my $end_date;
my $total_in = new Math::BigInt '0';
my $total_out = new Math::BigInt '0';
my $num_total_in = new Math::BigInt '0';
my $num_total_out = new Math::BigInt '0';
my $temp_out = new Math::BigInt '0';
my $temp_in = new Math::BigInt '0';
my $num_temp_out = new Math::BigInt '0';
my $num_temp_in = new Math::BigInt '0';
my $big_zero = new Math::BigInt '0';
my $str_out;
my $abridged = 1;
my @keys;
# Usage
sub usage
{
my $name = $0;
$name =~ s/^(.*)\\//;
print STDERR "\nUsage:\n";
print STDERR "\t$name <optional parameters> <server> <start date> <end date>\n";
print STDERR "\t\tDate format = yyyy-mm-dd (eg: 2004-06-08)\n";
print STDERR "\t$name <optional parameters> -f <money log file>\n\n";
print STDERR "Optional parameters:\n";
print STDERR "\t[-l <num>] [-s <time> | -S <time>] [-p | -n | -a] [-m <num> | -x <num> | -e <num>] [-d]\n";
print STDERR "\t-l <num>\tOnly process <num> lines of log file\n";
print STDERR "\t-s <time>\tStart processing at <time> \(eg \"2004-06-01 17:00:03\"\)\n";
print STDERR "\t-S <time>\tEnd processing at <time>\n";
print STDERR "\t-p \tSort results by player id number (default)\n";
print STDERR "\t-n \tSort results by number of transactions\n";
print STDERR "\t-a \tSort results by total amount of money changed\n";
print STDERR "\t-t \tSort results by time of most recent transaction\n";
print STDERR "\t-m <num>\tSet minimum threshold for sorted parameter\n";
print STDERR "\t-x <num>\tSet maximum threshold for sorted parameter\n";
print STDERR "\t-e <num>\tSet threshold to exactly <num>\n";
print STDERR "\t-d \tShow detailed output\n";
die "\n";
}
# Adds money / player id into hash
# Three arguments - key, value, amount of money, and which hash (to / from)
sub put_into
{
my %head;
my ($key, $val, $amt, $tim, $tf) = @_;
%head = ($tf ? %to_hash : %from_hash);
$head{$key} = {} if(!exists $head{$key});
$head{$key}->{$val} = [0, 0, 0] if(!exists $head{$key}->{$val});
$head{$key}->{$val}->[0] += 1;
$head{$key}->{$val}->[1] += $amt;
$head{$key}->{$val}->[2] = $tim if($tim gt $head{$key}->{$val}->[2]);
if($tf) { %to_hash = %head; }
else { %from_hash = %head; }
}
# Will sort numbers and strings - returns -1, 0, or 1
# Takes two arguments, to compare
sub str_num_cmp
{
my($a, $b) = @_;
# Both are numbers
return $a <=> $b if($a =~ /^\d+$/ && $b =~ /^\d+$/);
# Both are not numbers
return $a cmp $b if(!($a =~ /^\d+$/) && !($b =~ /^\d+$/));
# $a is a number, $b is not
return 1 if($a =~ /^\d+$/);
# $a is not a number, $ b is
return -1;
}
sub display_money_chart {
my $temp_total = new Math::BigInt '0';
my $temp_num = new Math::BigInt '0';
my $temp_hash = $_[0];
my $t_out = $_[1];
my @inner_keys;
my @sorted_vals;
@inner_keys = keys %$temp_hash;
@inner_keys = sort @inner_keys;
@sorted_vals = ();
foreach my $sub_elem (@inner_keys)
{
push(@sorted_vals, [$sub_elem, %$temp_hash->{$sub_elem}->[0], %$temp_hash->{$sub_elem}->[1], %$temp_hash->{$sub_elem}->[2]]);
}
@sorted_vals = sort { &str_num_cmp($b->[$sort_val], $a->[$sort_val]) } @sorted_vals;
@sorted_vals = reverse(@sorted_vals) if($sort_val == 0);
foreach my $val (@sorted_vals)
{
if((!exists $args{"m"} || (&str_num_cmp($val->[$sort_val], $min_thresh) == 0 || &str_num_cmp($val->[$sort_val], $min_thresh) == 1))
&& (!exists $args{"x"} || (&str_num_cmp($val->[$sort_val], $max_thresh) == 0 || &str_num_cmp($val->[$sort_val], $max_thresh) == -1))
&& (!exists $args{"e"} || &str_num_cmp($val->[$sort_val], $max_thresh) == 0))
{
if($t_out)
{
$total_out += $val->[2];
$num_total_out += $val->[1];
}
else
{
$total_in += $val->[2];
$num_total_in += $val->[1];
}
$temp_total += $val->[2];
$temp_num += $val->[1];
if(!$abridged)
{
printf "\t\t%-32s%-10d%-12d%-24s\n", $val->[0], $val->[1], $val->[2], $val->[3];
}
}
}
return ($temp_total, $temp_num);
}
$start_time = time;
&usage() if(!getopts('dpnatm:x:l:e:s:S:f:', \%args));
&usage if(((exists $args{"p"}) + (exists $args{"n"}) + (exists $args{"a"})) > 1);
&usage if((exists $args{"e"}) && (exists $args{"m"} || exists $args{"x"}));
# Process arguments
$sort_val = 0 if(exists $args{"p"});
$sort_val = 1 if(exists $args{"n"});
$sort_val = 2 if(exists $args{"a"});
$sort_val = 3 if(exists $args{"t"});
$max_cnt = $args{"l"} if(exists($args{"l"}));
$min_thresh = $args{"m"} if(exists($args{"m"}));
$max_thresh = $args{"x"} if(exists($args{"x"}));
$min_thresh = $max_thresh = $args{"e"} if(exists($args{"e"}));
$start_date = $args{"s"} if(exists($args{"s"}));
$end_date = $args{"S"} if(exists($args{"S"}));
$abridged = 0 if(exists($args{"d"}));
if(exists($args{"f"}))
{
&usage if(@ARGV != 0);
open (MONEY, $args{"f"});
}
else
{
&usage if(@ARGV != 3);
open(MONEY, "/m2/logsrv/log_dump.pl swg money $ARGV[0] $ARGV[1] $ARGV[2] |");
}
while (<MONEY>)
{
# Clear out three possible Unicode chars
s/^...20(\d{2})/20$1/;
chomp;
# Check start date if argument was passed
if(exists $args{"s"} && /^(\S+)\s+(\S+)/)
{
my $date = $1." ".$2;
next if($date lt $start_date);
}
# Check end date if argument was passed
if(exists $args{"S"} && /^(\S+)\s+(\S+)/)
{
my $date = $1." ".$2;
last if($date gt $end_date);
}
# Check a few special cases
if(/cash withdraw from bank by/ || /cash deposit to bank/)
{
#player deposited / withdrew money from bank
}
elsif(/logging out with/ || /logged in with/)
{
#player logged in / out
}
elsif(/^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.+) from (.+) to (.+), amount (\d+), (total|total\(from\)) -?(\d+):$/)
{
my $day = $1;
my $time = $2;
my $planet = $3;
my $vara = $4;
my $varb = $5;
my $varc = $6;
my $type = $7;
my $from = $8;
my $to = $9;
my $amount = $10;
my $total = $11;
my $from_named = $from =~ s/named account //;
my $to_named = $to =~ s/named account //;
#Strip the station id - can cause problems searching for player id
$from =~ s/StationId\(\d+\)//g;
$to =~ s/StationId\(\d+\)//g;
# Extract player Id number
$from =~ s/.*\((\d+)\).*/$1/ if($from =~ /Player/);
$to =~ s/.*\((\d+)\).*/$1/ if($to =~ /Player/);
# Special case where player has " from " in store title
if($type =~ /Player/)
{
$type =~ s/(.*) from /$1/;
$from =~ s/.*\((\d+)\).*/$1/;
}
# Add into the approproiate hash
if($from_named)
{
&put_into($from, $to, $amount, ($day." ".$time), 0);
}
if($to_named)
{
&put_into($to, $from, $amount, ($day." ".$time), 1);
}
}
else
{
print "$_\n";
die "Error in log file format.\n";
}
# Check counter
++$cnt;
last if($cnt == $max_cnt);
}
close (MONEY);
print "Named users transaction information:\n" if (!$abridged);
print "------------------------------------\n\n" if (!$abridged);
@keys = keys %from_hash;
push (@keys, (keys %to_hash));
@keys = sort @keys;
my $prev = -1;
@keys = grep($_ ne $prev && ($prev = $_), @keys);
printf "%s\t%s\t%s\t%s\t%s\t%s\n", "To:", "# To:", "From:", "# From:", "Delta:", "Account:" if($abridged);
foreach my $elem (@keys)
{
$temp_in = $big_zero;
$temp_out = $big_zero;
$num_temp_in = $big_zero;
$num_temp_out = $big_zero;
print "$elem:\n" if(!$abridged);
if(exists $from_hash{$elem})
{
if(!$abridged)
{
print "\tMoney from $elem:\n";
printf "\t\t%-32s%-10s%-12s%-24s\n", "To:", "# Times:", "Total Amt:", "Most Recent Time:";
printf "\t\t%-32s%-10s%-12s%-24s\n", "---", "--------", "----------", "-----------------";
}
($temp_out, $num_temp_out) = display_money_chart($from_hash{$elem}, 0);
if(!$abridged)
{
print "\tTotal $elem gave:\n";
print "\t\t$temp_out\n\n";
}
}
if(exists $to_hash{$elem})
{
if(!$abridged)
{
print "\tMoney to $elem:\n";
printf "\t\t%-32s%-10s%-12s%-24s\n", "From:", "# Times:", "Total Amt:", "Most Recent Time:";
printf "\t\t%-32s%-10s%-12s%-24s\n", "-----", "--------", "----------", "-----------------";
}
($temp_in, $num_temp_in) = display_money_chart($to_hash{$elem}, 1);
if(!$abridged)
{
print "\tTotal given to $elem:\n";
print "\t\t$temp_in\n\n";
}
}
printf "%s\t%s\t%s\t%s\t%s\t%s\n", "To:", "# To:", "From:", "# From:", "Delta:", "Account:" if(!$abridged);
$str_out = sprintf "%s\t%s\t%s\t%s\t%s\t%s\n", $temp_in, $num_temp_in, $temp_out, $num_temp_out, ($temp_out - $temp_in), $elem;
$str_out =~ s/\+//g;
print $str_out;
}
if(!$abridged)
{
print "\nTotal out:\t$total_out\n";
print "Total in:\t$total_in\n";
print "Total Delta:\t".($total_in - $total_out)."\n";
print "\nFinished in ".(time - $start_time)." seconds.\n";
}
else
{
$str_out = sprintf "\n%s\t%s\t%s\t%s\t%s\t%s\n", $total_out, $num_total_out, $total_in, $num_total_in, ($total_in - $total_out), "Total";
$str_out =~ s/\+//g;
print $str_out;
}

174
tools/NormalizeExcelXml.pl Executable file
View File

@@ -0,0 +1,174 @@
#!/usr/bin/perl -i
use XML::Parser::PerlSAX;
die "usage: NormalizeExcelXml.pl <filename>\n" unless (@ARGV == 1);
$filename = $ARGV[0];
die "$filename not found\n" unless (-e $filename);
die "$filename not writable\n" unless (-w $filename);
$backup = $filename . "~";
die "Could not rename $filename -> $backup\n" unless (rename ($filename, $backup));
open (INFILE, "<$backup");
open (OUTFILE, ">$filename");
select(OUTFILE);
my $handler = MyHandler->new();
my $parser = XML::Parser::PerlSAX->new( Handler => $handler );
print "<?xml version=\"1.0\"?>";
$parser->parse(Source => { ByteStream => \*INFILE });
package MyHandler;
sub new {
my ($type) = @_;
my $self = {};
$quiet_level = 0;
$opened = 0;
$indent_level = "";
$open_tag = "";
$in_cell = 0;
%bad_elements =
(
"NamedCell", 1,
"Styles", 1,
);
%bad_attributes =
(
"ss:StyleID", 1,
"ss:AutoFitWidth", 1,
);
return bless ($self, $type);
}
sub start_element
{
my ($self, $element) = @_;
my $name = $element->{Name};
if (exists $bad_elements{$name})
{
$quiet_level += 1;
}
if ($quiet_level == 0)
{
if (!$open_tag eq "")
{
print ">";
}
if (! $in_cell )
{
print "\n$indent_level";
}
print "<$name";
foreach $z (keys %{$element->{Attributes}})
{
if (!exists $bad_attributes{$z})
{
print " " . $z . '="';
$_ = $element->{Attributes}->{$z};
s/\"/&quot;/g;
s/</&lt;/g;
s/>/&gt;/g;
print $_;
print '"';
}
}
$open_tag = $name;
#$indent_level = $indent_level . ' ';
$opened = 1;
if ($name eq "Cell")
{
$in_cell = 1;
}
}
}
sub end_element {
my ($self, $element) = @_;
my $name = $element->{Name};
if ($quiet_level == 0)
{
#chop $indent_level;
if ($open_tag eq $name)
{
print "/>";
}
else
{
if (!$opened && !$in_cell)
{
print "\n$indent_level";
}
print "</$name>";
}
$open_tag = "";
$opened = 0;
}
if ($name eq "Cell")
{
$in_cell = 0;
}
if (exists $bad_elements{$name})
{
$quiet_level -= 1;
}
}
sub characters {
my ($self, $characters) = @_;
$_ = $characters->{Data};
chomp;
if (/\S/)
{
s/\"/&quot;/g;
s/</&lt;/g;
s/>/&gt;/g;
if (!$open_tag eq "")
{
print ">";
$open_tag = "";
}
print $_;
}
}

37
tools/ScanInc.btm Normal file
View File

@@ -0,0 +1,37 @@
@echo off
@rem This file is to be used on includePaths.rsp files to check the validity of included folders
set slMode=delete
set slIncludeFile=%1
@rem echo %slIncludeFile
if not exist "%slIncludeFile" (echo %slIncludeFile not found & goto end)
set slFileLine=%@TRIM[%@LINE[%slIncludeFile, 0]]
set slInclude=%@INSTR[1, 8, %slFileLine]
if "%slInclude" == "#include" goto process
if "%slInclude" == "#ifndef" p4 edit %slIncludeFile
if "%slInclude" == "#error o" p4 delete %slIncludeFile
goto skip
:process
set slFileLine2=%@INSTR[17, 100, %slFileLine]
set slLineLength=%@LEN[%slFileLine2]
set slLine=%@LEFT[%slLineLength, %slFileLine2]
set slLine=%@REPLACE[/,\,%slLine]
set slLine=%@TRIM[%slLine]
if not exist "%slLine" (if not "%slLine" == "" (echo %2/%slIncludeFile & echo x "%slLine" & p4 %slMode %slIncludeFile))
goto end
:skip
echo skipping %slIncludeFile {%slInclude} [%slFileLine]
:end
@rem cleanup variables
set slFileCount=
set i=
set slFileLine=
set slErrors=
set slIncludeFile=
set slLine=

64
tools/ScanIncs.btm Normal file
View File

@@ -0,0 +1,64 @@
@echo off
goto end
:scanSub1
pushd %i
for /a:d j in (*) do (if "%@TRIM[%@LEFT[2, %j]]" != "." (gosub scanSub2))
popd
return
:scanSub2
pushd %j
for /a:d k in (*) do (if "%@TRIM[%@LEFT[2, %k]]" != "." (gosub scanSub3))
popd
return
:scanSub3
if not isdir %k\include\public\%k goto missingpublic
pushd %k
for l in (include\public\%k\*) do (if "%@TRIM[%@LEFT[2, %k]]" != "." (gosub scanSub4public))
popd
if not isdir %k\include\private\%k goto missingprivate
pushd %k\include\private\%k
for l in (include\private\%k\*) do (if "%@TRIM[%@LEFT[2, %k]]" != "." (gosub scanSub4private))
popd
return
:scanSub4public
call ScanInc %l %k include\public
return
:scanSub4private
call ScanInc %l %k include\private
return
:missingpublic
@rem echo missing %k\include\public\%k
return
:missingprivate
@rem echo missing %k\include\private\%k
return
pushd ..\src\engine
set i=shared
gosub scanSub1
set i=client
gosub scanSub1
set i=server
gosub scanSub1
popd
pushd ..\src\game
set i=shared
gosub scanSub1
set i=client
gosub scanSub1
set i=server
gosub scanSub1
popd
:end

33
tools/ScanLnt.btm Normal file
View File

@@ -0,0 +1,33 @@
@echo off
@rem This file is to be used on project.lnt files to check the validity of included folders
set slLintFile=%1
if "%1" == "" set slLintFile=project.lnt
@rem count number of lines
set slFileCount=%@LINES[%slLintFile]
set slErrors=0
echo Scanning %2/%slLintFile
@rem for all lines in the file
do i = 0 to %slFileCount by 1
set slFileLine=%@TRIM[%@LINE[%slLintFile, %i]]
set slLineLength=%@LEN[%slFileLine]
set slRightLength=%@DEC[%@DEC[%slLineLength]]
set slDirectory=%@RIGHT[%slRightLength, %slFileLine]
set slIsDirectory=%@TRIM[%@LEFT[3, %slFileLine]]
if "%slIsDirectory" == "-i" (if not isdir "%slDirectory" (set slErrors=%@INC[%slErrors] & echo x [%@INC[%i]] "%slDirectory"))
enddo
echo %slErrors error(s) found
@rem cleanup variables
set slFileCount=
set i=
set slFileLine=
set slLineLength=
set slRightLength=
set slDirectory=
set slIsDirectory=
set slErrors=

49
tools/ScanLnts.btm Normal file
View File

@@ -0,0 +1,49 @@
@echo off
pushd ..\src\engine
set i=shared
gosub scanSub1
set i=client
gosub scanSub1
set i=server
gosub scanSub1
popd
pushd ..\src\game
set i=shared
gosub scanSub1
set i=client
gosub scanSub1
set i=server
gosub scanSub1
popd
goto end
:scanSub1
pushd %i
for /a:d j in (*) do (if "%@TRIM[%@LEFT[2, %j]]" != "." (gosub scanSub2))
popd
return
:scanSub2
pushd %j
for /a:d k in (*) do (if "%@TRIM[%@LEFT[2, %k]]" != "." (gosub scanSub3))
popd
return
:scanSub3
pushd %k
if not exist project.lnt goto missing
:found
echo ----------
call ScanLnt project.lnt %i/%j/%k
popd
return
:missing
echo missing project.lnt in %i/%j/%k
popd
return
:end

30
tools/ScanRsp.btm Normal file
View File

@@ -0,0 +1,30 @@
@echo off
@rem This file is to be used on includePaths.rsp files to check the validity of included folders
set slIncludeFile=%1
if "%1" == "" set slIncludeFile=includePaths.rsp
@rem count number of lines
set slFileCount=%@LINES[%slIncludeFile]
set slErrors=0
echo Scanning %2/%slIncludeFile
@rem for all lines in the file
do i = 0 to %slFileCount by 1
set slDirectory=%@TRIM[%@LINE[%slIncludeFile, %i]]
if not isdir "%slDirectory" (if not "%slDirectory" == "" (if not "%slDirectory" == "..\..\include\private" (if not "%slDirectory" == "../../include/private" (set slErrors=%@INC[%slErrors] & echo x [%@INC[%i]] "%slDirectory"))))
enddo
echo %slErrors error(s) found
@rem if not "%slErrors" == "0" p4 edit %slIncludeFile & pause
@rem cleanup variables
set slFileCount=
set i=
set slFileLine=
set slLineLength=
set slRightLength=
set slDirectory=
set slIsDirectory=
set slErrors=

54
tools/ScanRsps.btm Normal file
View File

@@ -0,0 +1,54 @@
@echo off
pushd ..\src\engine
set i=shared
gosub scanSub1
set i=client
gosub scanSub1
set i=server
gosub scanSub1
popd
pushd ..\src\game
set i=shared
gosub scanSub1
set i=client
gosub scanSub1
set i=server
gosub scanSub1
popd
goto end
:scanSub1
pushd %i
for /a:d j in (*) do (if "%@TRIM[%@LEFT[2, %j]]" != "." (gosub scanSub2))
popd
return
:scanSub2
pushd %j
for /a:d k in (*) do (if "%@TRIM[%@LEFT[2, %k]]" != "." (gosub scanSub3))
popd
return
:scanSub3
if not isdir %k\build\win32 goto missing
pushd %k\build\win32
:found
echo ----------
if not exist "includePaths.rsp" goto missingp
call ScanRsp includePaths.rsp %i/%j/%k/build/win32
popd
return
:missing
echo missing includePaths.rsp in %i/%j/%k/build/win32
return
:missingp
echo missing includePaths.rsp in %i/%j/%k/build/win32
popd
return
:end

144
tools/ScanScript.pl Executable file
View File

@@ -0,0 +1,144 @@
#! /usr/bin/perl
# ======================================================================
# ======================================================================
use strict;
use warnings;
# ======================================================================
# Globals
# ======================================================================
my %str_to_tags;
my %str_to_files;
my $tmprsp = "a.rsp";
my $name = $0;
$name =~ s/^(.*)\\//;
# ======================================================================
# Subroutines
# ======================================================================
sub usage
{
die "\nTool used to scan through conversation scripts and verify that all .stf files have the appropriate tags\n\n".
"\tUsage\n".
"\t\t$name <script file>\n\n";
}
sub testfile
{
#p4 fstat //depot/swg/current/data/.../string/en/bartender.stf
#echo c:\work\swg\current\data\sku.0\sys.server\built\game\string\en\bartender.stf > a.rsp
#WordCountTool.exe -d a.rsp
my $file = shift @_;
my $path = $file;
$path =~ s/\./\//g;
my @files;
open(P4, "p4 fstat //depot/swg/current/data/.../string/en/${path}.stf | ") or die "Cannot open file: $path\n";
while(<P4>)
{
push @files, $1 if(/^\.\.\. clientFile (.+)$/);
}
close(P4);
foreach my $elem (@files)
{
print "\t$elem:\n";
my %filetags;
system("echo $elem > $tmprsp");
open(WORDCOUNT, "WordCountTool.exe -d $tmprsp | ");
while(<WORDCOUNT>)
{
$filetags{"\"$1\""} = 0 if(/^\t(\S+)\t/);
}
close(WORDCOUNT);
my $ref = $str_to_tags{$file};
my $missing = 0;
foreach my $tag (sort keys %$ref)
{
if(!exists $filetags{$tag})
{
print "\t\tis missing $tag\n";
$missing = 1;
}
}
$missing ? print "\n" : print "\t\tNone missing\n\n";
}
unlink($tmprsp);
}
# ======================================================================
# Main
# ======================================================================
&usage() if(@ARGV != 1);
my $scriptfile = shift;
print "Scanning script file...\n";
open(SCRIPT, "<$scriptfile");
while(<SCRIPT>)
{
$str_to_files{$2} = $3 if(/(const)?\s+string\s+([A-Za-z_]+)\s+=\s+"([A-Za-z_\.]+)"/);
#if(/(new)?\s+string_id\s*\(\s*([A-Za-z_]+)\s*,\s*"([A-Za-z_]+)"\s*\)/)
if(/(new)?\s+string_id\s*\(\s*([A-Za-z_]+)\s*,\s*(.+)\s*\)/)
{
my $string = $2;
my $tagline = $3;
$str_to_tags{$str_to_files{$string}} = {} if(!exists $str_to_tags{$str_to_files{$string}});
if($tagline =~ s/"(.+)"\s*\+\s*rand\s*\(\s*(\d)+\s*,\s*(\d)+\s*\)//)
{
my $tagline = $1;
my $num = $2;
my $end = $3;
while($num <= $end)
{
$str_to_tags{$str_to_files{$string}}->{"\"${tagline}$num\""} = 0;
++$num;
}
}
else
{
$tagline =~ s/\)//g;
$str_to_tags{$str_to_files{$string}}->{$tagline} = 0;
}
}
}
close(SCRIPT);
foreach my $str (sort keys %str_to_tags)
{
my $hash_ref = $str_to_tags{$str};
print "\nFile: '$str' needs to contain\n";
foreach my $tag (sort keys %$hash_ref)
{
print "\t$tag\n";
}
}
print "\nScanning for missing elements of script files...\n";
foreach my $filename (sort keys %str_to_tags)
{
testfile($filename);
}

43
tools/SwgClientClean.pl Executable file
View File

@@ -0,0 +1,43 @@
#!/usr/bin/perl -w
use BuildFunctions;
###
# Copyright (C)2000-2002 Sony Online Entertainment Inc.
# All Rights Reserved
#
# Title: SwgClientClean.pl
# Description: Build release and debug SWGGameServer. Emails the resulting log files to gmcdaniel.
# @author $Author: gmcdaniel $
# @version $Revision: #3 $
##
########## MAIN ##########
##
# Delete compile directory for clean build
system("c:\\4nt302\\4nt /c del /s /y ..\\src\\compile");
#
## End of Delete compile directory for clean build
##
# Build Projects and Check for Errors
build_project ("SwgClient");
Check_For_Warnings_and_Errors("SwgClient","SwgClient.exe");
#
## End of Build Projects and Check for Errors
########## END OF MAIN ##########

44
tools/SwgGameServerClean.pl Executable file
View File

@@ -0,0 +1,44 @@
#!/usr/bin/perl -w
use BuildFunctions;
###
# Copyright (C)2000-2002 Sony Online Entertainment Inc.
# All Rights Reserved
#
# Title: SwgGameServerClean.pl
# Description: Build release and debug SWGGameServer. Emails the resulting log files to gmcdaniel.
# @author $Author: gmcdaniel $
# @version $Revision: #3 $
##
########## MAIN ##########
##
# Delete compile directory for clean build
system("c:\\4nt302\\4nt /c del /s /y ..\\src\\compile");
#
## End of Delete compile directory for clean build
##
# Build Projects and Check for Errors
build_project ("SwgGameServer");
Check_For_Warnings_and_Errors("SwgGameServer","SwgGameServer.exe");
#
## End of Build Projects and Check for Errors
########## END OF MAIN ##########

48
tools/SwgGodClientClean.pl Executable file
View File

@@ -0,0 +1,48 @@
#!/usr/bin/perl -w
use BuildFunctions;
###
# Copyright (C)2000-2002 Sony Online Entertainment Inc.
# All Rights Reserved
#
# Title: SwgGodClientClean.pl
# Description: Build release and debug SWGGameServer. Emails the resulting log files to gmcdaniel.
# @author $Author: gmcdaniel $
# @version $Revision: #3 $
##
########## MAIN ##########
##
# Delete compile directory for clean build
system("c:\\4nt302\\4nt /c del /s /y ..\\src\\compile");
#
## End of Delete compile directory for clean build
##
# Build Projects and Check for Errors
build_project ("SwgGodClient");
Check_For_Warnings_and_Errors("SwgGodClient","SwgGodClient.exe");
#
## End of Build Projects and Check for Errors
########## END OF MAIN ##########

Binary file not shown.

BIN
tools/TreeFileBuilder Normal file

Binary file not shown.

BIN
tools/TreeFileBuilder.exe Normal file

Binary file not shown.

BIN
tools/TreeFileExtractor.exe Normal file

Binary file not shown.

Binary file not shown.

BIN
tools/VersionNumber Normal file

Binary file not shown.

BIN
tools/VersionNumber.exe Normal file

Binary file not shown.

BIN
tools/WordCountTool.exe Normal file

Binary file not shown.

46
tools/allClientBuildClean.pl Executable file
View File

@@ -0,0 +1,46 @@
#!/usr/bin/perl -w
use BuildFunctions;
###
# Copyright (C)2000-2002 Sony Online Entertainment Inc.
# All Rights Reserved
#
# Title: allClientBuildClean.pl
# Description: Builds all_Client debug and release and sends log files to gmcdaniel
# @author $Author: gmcdaniel $
# @version $Revision: #3 $
###
########## MAIN ##########
##
# Delete compile directory for clean build
system("c:\\4nt302\\4nt /c del /s /y ..\\src\\compile");
#
## End of Delete compile directory for clean build
##
# Build Projects and Check for Errors
build_project ("_all_client");
Check_For_Warnings_and_Errors("_all_client","_all_client");
#
## End of Build Projects and Check for Errors
########## END OF MAIN ##########

View File

@@ -0,0 +1,147 @@
#!/perl/bin
die "usage: perl assignVertexShaderConstants.pl input_template hlsl.inc dx.inc shaderBuilder.inc\n" if (@ARGV != 4);
my $register = 0;
# define the sizes of some intrinsic types
my %size;
$size{"float"} = 1;
$size{"float2"} = 1;
$size{"float3"} = 1;
$size{"float4"} = 1;
$size{"float4x4"} = 4;
# open all the files
open(INPUT, shift);
open(HLSL, ">".shift);
open(CPP, ">".shift);
open(SB, ">".shift);
while (<INPUT>)
{
chomp;
if (/^struct/)
{
# begin recording information about a struct
print HLSL "$_\n";
s/^struct\s+//;
$struct = $_;
}
elsif ($struct ne "" && /^};/ )
{
# end recording information about a struct
print HLSL "$_\n";
undef $struct;
}
elsif (/^\/\// || /^#pragma/ || /^{/ || /^\s*$/)
{
# copy any comments, pragmas, open curly braces, or blank lines
print HLSL "$_\n";
}
elsif (/^static const int /)
{
# record global integer values for array sizes
print HLSL "$_\n";
s/^static const int //;
s/;//;
s/=//;
($variable, $value) = split;
$variable{$variable} = $value;
}
else
{
# assume this is a global variable or structure member
s/;//;
my $array = 0;
my $count = 1;
if (/\[(.+)\]/)
{
if (defined $variable{$1})
{
$count = $variable{$1};
}
else
{
$count = $1;
}
$array = 1;
}
($type, $variable) = split;
die "unknown size for $type\n" if (!defined $size{$type});
if (defined $struct)
{
print HLSL "$_;\n";
$size{$struct} += $size{$type} * $count;
@array = ( "" );
@array = (0 .. $count-1) if ($array);
$variable =~ s/\[.*//;
foreach $index (@array)
{
# handle structure members
$index = "[$index]" if ($index ne "");
if (defined $members{$type})
{
my @members = split (/\s+/, $members{$type});
while (@members)
{
my $member = shift @members;
my $size = shift @members;
$members{$struct} .= " " if (defined $members{$struct});
$members{$struct} .= "$variable$index.$member $size";
}
}
else
{
$members{$struct} .= " " if (defined $members{$struct});
$members{$struct} .= "$variable$index $size{$type}";
}
}
}
else
{
# handle global variables
s/;//;
if (defined $members{$type})
{
# emit registers for all the stucture members
my $offset = 0;
my @members = split (/\s+/, $members{$type});
while (@members)
{
my $member = shift @members;
print SB "\t\taddConstantRegister(\"$variable.$member\", ", $register + $offset, ");\n";
$offset += shift @members;
}
}
else
{
# emit register for the variable
print SB "\t\taddConstantRegister(\"$variable\", $register);\n";
}
print CPP "\tVSCR_$variable = $register,\n";
print HLSL "$_ : register(c$register);\n";
$register += $size{$type} * $count;
}
}
}
print CPP "\tVSCR_MAX", " = $register\n";
close(INPUT);
close(HLSL);
close(CPP);
close(SB);

View File

@@ -0,0 +1,40 @@
use POSIX ":sys_wait_h";
use FindBin '$Bin';
require "$Bin/taskmanager.pl";
require "$Bin/centralserver.pl";
require "$Bin/passfail.pl";
require "$Bin/loginserver.pl";
require "$Bin/databaseserver.pl";
require "$Bin/planetserver.pl";
$target = $ARGV[0];
my $testPlanet = "tatooine";
if($target eq "")
{
fail("target (debug or release) not specified in test script\n");
}
#taskmanagerStartupShutdown($target);
#centralServerStartupShutdown($target);
loginServerStartup($target);
clusterStartup($target);
centralServerRunning($target);
databaseServerConnectedToCentralServer($target);
databaseServerRunning($target);
planetServerConnected($target);
hasPlanetServer($target, $testPlanet);
planetServerRunning($target, $testPlanet);
# gameServerRunning($target);
# chatServerRunning($target);
# commoditiesServerRunning($target);
# connectionServerRunning($target);
# customerServiceServerRunning($target);
# logServerRunning($target);
# metricsServerRunning($target);
# transferServerRunning($target);
# clusterIsReady($target);
loginServerShutdown($target);
clusterShutdown($target);

View File

@@ -0,0 +1,98 @@
use POSIX ":sys_wait_h";
use FindBin '$Bin';
require "$Bin/passfail.pl";
sub backgroundProcess
{
my($prefix, $program, $timeout, $funcPtr) = @_;
$cmd = "$prefix/$program";
$childId = fork();
if($childId == 0)
{
$result = system("$cmd");
exit($result);
}
else
{
$runTime = time();
do
{
$elapsed = time() - $runTime;
if($elapsed > $timeout)
{
kill(11, $childId);
chomp($cwd = `pwd`);
fail("$cmd did not exit in time. Sending SIGSEGV to force a core dump in $cwd");
}
if(defined($funcPtr))
{
&$funcPtr();
}
$kid = waitpid($childId, WNOHANG);
} until $kid > 0 ;
$taskResult = $?;
if($taskResult != 0)
{
fail("$cmd did not exit cleanly!!");
}
}
return 1;
}
sub startBackgroundProcess
{
my($prefix, $program, $timeout, $funcPtr) = @_;
$cmd = "$prefix/$program";
$childId = fork();
if($childId == 0)
{
$result = system("$cmd");
exit($result);
}
else
{
$runTime = time();
do
{
$elapsed = time() - $runTime;
if($elapsed > $timeout)
{
kill(11, $childId);
chomp($cwd = `pwd`);
fail("$cmd did not respond to run query in time. Sending SIGSEGV to force core dump in $cwd");
}
$functionResult = 0;
if(defined($funcPtr))
{
$functionResult = &$funcPtr();
}
else
{
$functionResult = 1;
}
$kid = waitpid($childId, WNOHANG);
} until $kid > 0 || $functionResult != 0;
$taskResult = $?;
if(defined($funcPtr))
{
if($functionResult == -1)
{
fail("run query function for $cmd returned -1. Failed to start background process.");
}
}
elsif($kid > 0 && $taskResult != 0)
{
fail("$cmd failed to start properly");
}
}
return $childId;
}
1;

View File

@@ -0,0 +1,45 @@
use FindBin '$Bin';
require "$Bin/passfail.pl";
require "$Bin/background_process.pl";
sub centralServerStartupShutdown
{
$passFailMessage = "CentralServer startup and shutdown";
my($prefix) = @_;
failOnFalse(backgroundProcess($prefix, "CentralServer -- -s CentralServer shutdown=true 2>/dev/null", 10), $passFailMessage, $passFailMessage);
}
sub centralServerRunning
{
my($prefix) = @_;
my $result = runCommand($prefix, "runState");
my $testMessage = "CentralServer running";
failOnFalse($result eq "running", $testMessage, $testMessage);
}
sub databaseServerConnectedToCentralServer
{
my($prefix) = @_;
my $result = "";
my $passFailMessage = "DatabaseServer connected to CentralServer";
# test that the database server has connected to the
# central server by querying Central for a db connection.
# poll CentralServer repeatedly until it responds with a "1"
# or more than 10 seconds has passed
failOnFalse(runCommandUntil($prefix, "dbconnected", "1", 10), $passFailMessage, $passFailMessage);
}
sub planetServerConnected
{
my($prefix) = @_;
my $passFailMessage = "PlanetServer connected to CentralServer";
failOnFalse(runCommandUntil($prefix, "getPlanetServersCount", "1", 10, sub { $_[0] > 0; }), $passFailMessage, $passFailMessage);
}
sub hasPlanetServer
{
my($prefix, $planetName) = @_;
my $passFailMessage = "PlanetServer for $planetName is connected to CentralServer";
failOnFalse(runCommandUntil($prefix, "hasPlanetServer $planetName", "1", 10), $passFailMessage, $passFailMessage);
}

View File

@@ -0,0 +1,13 @@
use FindBin '$Bin';
require "$Bin/passfail.pl";
require "$Bin/background_process.pl";
sub databaseServerRunning
{
my($prefix) = @_;
my $result = runCommand($prefix, "database runState");
my $testMessage = "DatabaseServer reports a true run state";
failOnFalse($result eq "running", $testMessage, $testMessage);
}
1;

View File

@@ -0,0 +1,55 @@
use FindBin '$Bin';
require "$Bin/passfail.pl";
require "$Bin/background_process.pl";
$loginServerPid = 0;
sub loginServerStartup
{
$passFailMessage = "LoginServer startup";
my($prefix) = @_;
# determin the user id
$uid = getpwuid($<);
my $branch = "";
#determing the branch
@dirs = split('/', $Bin);
$x = 0;
for $i(@dirs)
{
if($i eq "swg")
{
if(@dirs[$x+2] eq "tools")
{
$branch = @dirs[$x+1];
break;
}
}
$x++;
}
$dbuid = "$uid\_$branch";
$loginServerPid = startBackgroundProcess($prefix, "LoginServer -- -s LoginServer databaseProtocol=OCI DSN=swodb databaseUID=$dbuid databasePWD=changeme 2>/dev/null", 10);
failOnFalse($loginServerPid, $passFailMessage, $passFailMessage);
}
sub loginServerShutdown
{
if($loginServerPid != 0)
{
$kid = 0;
do
{
$kid = waitpid($loginServerPid, WNOHANG);
if($kid == 0)
{
system("echo \"login exit\" | debug/ServerConsole -- -s ServerConsole > /dev/null");
}
} until $kid > 0;
failOnFalse($? == 0, "LoginServer shutdown", "LoginServer shutdown");
}
}
1;

View File

@@ -0,0 +1,28 @@
sub pass
{
my ($message) = @_;
print "PASS: $message\n";
}
sub fail
{
my ($message) = @_;
print "FAIL: $message\n";
exit(1);
}
sub failOnFalse
{
my ($result, $failMessage, $passMessage) = @_;
if($result == 0)
{
fail($failMessage);
}
else
{
pass($passMessage);
}
}
1;

View File

@@ -0,0 +1,11 @@
use FindBin '$Bin';
require "$Bin/passfail.pl";
require "$Bin/background_process.pl";
sub planetServerRunning
{
my($prefix, $planetName) = @_;
my $passFailMessage = "PlanetServer $planetName reports a true run state";
my $result = runCommandUntil($prefix, "planet $planetName runState", "running", 10);
failOnFalse($result eq "running", $passFailMessage, $passFailMessage);
}

View File

@@ -0,0 +1,69 @@
use FindBin '$Bin';
require "$Bin/passfail.pl";
sub runCommandUntil
{
my($prefix, $command, $expect, $timeout, $evalFunc) = @_;
my $startTime = time();
my $runTime = time() - $startTime;
my $result = "";
if(!defined($timeout))
{
$timeout = 0;
}
do
{
$result = runCommand($prefix, $command);
if($timeout > 0)
{
$runTime = time() - $startTime;
}
} until ($result eq $expect || ($timeout > 0 && $runTime > $timeout) || (defined($evalFunc) && &$evalFunc($result)) );
$returnValue = 0;
if(($result eq $expect || (defined($evalFunc) && &$evalFunc($result))) && ($timeout > 0 && $timeout >= $runTime || $timeout == 0))
{
$returnValue = $result;
}
return $returnValue;
}
sub runCommand
{
my($prefix, $command, $port) = @_;
my $result = "";
$shellCommand = "echo \"$command\" | $prefix/ServerConsole";
if(defined($port))
{
$shellCommand .= " -- -s ServerConsole serverPort=$port";
}
$shellCommand .= " 2>&1|";
open(COMMANDOUTPUT, $shellCommand) or fail("Failed to execute $shellCommand!\n");
while(<COMMANDOUTPUT>)
{
$result .= $_;
}
return $result;
}
sub runTaskCommand
{
my($prefix, $command) = @_;
my $result = "";
$result = runCommand($prefix, $command, 60000);
return $result;
}
1;

View File

@@ -0,0 +1,44 @@
use FindBin '$Bin';
require "$Bin/passfail.pl";
require "$Bin/background_process.pl";
require "$Bin/serverconsole.pl";
$taskManagerPid = 0;
sub taskmanagerStartupShutdown
{
my ($prefix) = @_;
$passFailMessage = "TaskManager startup and shutdown";
failOnFalse(backgroundProcess($prefix, "TaskManager -- -s TaskManager autoStart=false 2>/dev/null", 10, sub {system("echo \"exit\" | debug/ServerConsole -- -s ServerConsole serverPort=60000 > /dev/null");}), $passFailMessage, $passFailMessage);
}
sub clusterStartup
{
my ($prefix) = @_;
$passFailMessage = "TaskManager cluster startup";
$taskManagerPid = startBackgroundProcess($prefix, "TaskManager -- \@taskmanager.cfg 2>/dev/null", 10, sub { return 1; });
$result = "";
do
{
$result = runTaskCommand($prefix, "runState");
} until($result eq "running");
failOnFalse($taskManagerPid > 0, $passFailMessage, $passFailMessage);
do
{
$result = runCommand($prefix, "runState");
} until($result eq "running");
pass("CentralServer cluster startup");
}
sub clusterShutdown
{
my ($prefix) = @_;
do
{
$result = runTaskCommand($prefix, "exit");
} until($result eq "exiting");
}
1;

BIN
tools/bison.exe Normal file

Binary file not shown.

37
tools/buildAllVcproj.pl Executable file
View File

@@ -0,0 +1,37 @@
my @vcprojs;
print "Getting list\n";
open (FIND, "c:/cygwin/bin/find ../src -name \"settings.rsp\" |");
while (<FIND>)
{
chomp;
s/\/(\w*)\/build\/win32\/settings\.rsp/\/$1\/build\/win32\/$1\.vcproj/g;
push @vcprojs, $_;
}
close (FIND);
print "Editing\n";
open (P4, "| p4 -x - edit");
print P4 join("\n", @vcprojs);
close (P4);
my @errorList;
foreach (@vcprojs)
{
print "Building $_\n";
if (system ("buildVcproj.pl $_"))
{
push @errorList, $_;
}
}
print "Reverting\n";
open (P4, "| p4 -x - revert -a");
print P4 join("\n", @vcprojs);
close (P4);
if (@errorList)
{
die "ERROR!: Failed to build to following projects:\n", (join "\n", @errorList), "\n";
}

75
tools/buildAppearanceTable.pl Executable file
View File

@@ -0,0 +1,75 @@
#! /usr/bin/perl
die "usage: perl buildAppearanceTable directory [directory ...]\n" if (@ARGV == 0 || $ARGV[0] eq "-h");
$debug = 0;
# scan the file looking for an appearance or portal layout name
sub do_file
{
local $_;
my $file = $_[0];
print STDERR "scanning $file\n" if ($debug);
open(FILE, $file);
while (<FILE>)
{
chomp;
if (/appearanceFilename/ || /portalLayoutFilename/)
{
s/^[^"]+"//;
s/"[^"]*$//;
tr/A-Z/a-z/;
tr#\\#/#;
$match{$file} = $_ if ($_ ne "");
print STDERR "match $file $_\n" if ($debug);
}
}
close(FILE);
}
# recursively scan a directory
sub do_dir
{
local $_;
my $dir = $_[0];
print STDERR "processing $dir\n" if ($debug);
opendir(DIR, $dir) || return;
my @filenames = readdir(DIR);
closedir(DIR);
for (@filenames)
{
next if $_ eq ".";
next if $_ eq "..";
$pathed = $dir . "/" . $_;
if (-d $pathed)
{
&do_dir($pathed);
}
elsif (/\.tpf$/)
{
&do_file($pathed);
}
}
}
# process all the command line directories
while (@ARGV)
{
&do_dir(shift @ARGV);
}
# spit out tab separated data
foreach (sort keys %match)
{
print $_, "\t", $match{$_}, "\n";
}

68
tools/buildAppearanceUsage.pl Executable file
View File

@@ -0,0 +1,68 @@
#! /usr/bin/perl
die "usage: perl buildAppearanceUsage buildAppearanceTableOutputFile directory [directory ...]\n" if (@ARGV == 0 || $ARGV[0] eq "-h");
$debug = 0;
# recursively scan a directory
sub do_dir
{
local $_;
my $real = $_[0];
my $display = $_[1];
print STDERR "processing $real\n" if ($debug);
opendir(DIR, $real) || return;
my @filenames = readdir(DIR);
closedir(DIR);
for (@filenames)
{
next if $_ eq ".";
next if $_ eq "..";
if (-d "$real/$_")
{
if ($display ne "")
{
&do_dir("$real/$_", "$display/$_");
}
else
{
&do_dir("$real/$_", "$_");
}
}
elsif (/\.apt$/)
{
$add = "$display/$_";
$add =~ s#^.*/appearance/#appearance/#;
print STDERR "adding file $add\n" if ($debug);
$apt{"$add"} = 0;
}
}
}
$output = shift @ARGV;
# process all the command line directories
while (@ARGV)
{
&do_dir(shift @ARGV, "");
}
open(FILE, $output);
while (<FILE>)
{
chomp;
($object, $appearance) = split(/\t+/);
$apt{$appearance} += 1;
}
close(FILE);
# spit out tab separated data
foreach (sort keys %apt)
{
print $apt{$_}, "\t", $_, "\n";
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,153 @@
#!/bin/sh
# Copyright 2003, Sony Online Entertainment.
# All rights reserved.
#
# Based off a script originally written by Rick Delashmit.
# PURPOSE: Build the infrequently-changing Linux libraries that
# typically live in perforce as binaries. The gcc 2.95.3 C++ libraries are
# incompatible with the gcc 3.x C++ libraries. This script builds
# all the libraries that normally exist in perforce as binaries.
# NOTE: This script will fail if the user has not taken care to remove
# *.a and *.so from their client spec. Those files will be read-only and
# the new compiled versions will fail to replace them. As of this writing,
# the only .a file that should exist in perforce is the one for pcre in
# swg/$BRANCH/src/external/3rd/library/pcre/*.
# USAGE: run this script in the from the base directory of a branch.
#
# Here's some examples of branch directories:
# ~/swg/current
# ~/swg/test
# /swo/swg/current
# BUGS:
#
# * This script does no error checking on the result of the builds. If
# the caller does not watch the output, it is possible this script will fail.
#
# * This script has failed to build in the live branch on Matt Bogue's machine.
# Rick and I could not resolve the apparent bash substitution issue that was
# occurring. Our workaround was to link the live branch's
# external/3rd/library/platform/libs directory to the corresponding directory
# in the current branch.
export BASEDIR=`pwd`
export TEAMBUILDER=0
export PLATFORM=linux
# chatapi
cd $BASEDIR/src/external/3rd/library/soePlatform/ChatAPI2/ChatAPI/projects/Chat/ChatMono
make debug release
mkdir -p ../../../../../libs/Linux-Debug
mkdir -p ../../../../../libs/Linux-Release
cp ../../../lib/debug/libChatAPI.a ../../../../../libs/Linux-Debug/
cp ../../../lib/release/libChatAPI.a ../../../../../libs/Linux-Release/
# stlport
cd $BASEDIR/src/external/3rd/library/stlport453/src
make -f gcc-linux.mak
# zlib
# Note: just link zlib to the zlib already installed under Linux.
mkdir -p $BASEDIR/src/external/3rd/library/zlib/lib/linux
ln -s -f /usr/lib/libz.a $BASEDIR/src/external/3rd/library/zlib/lib/linux/libz.a
# loginapi
cd $BASEDIR/src/external/3rd/library/platform/projects/Session/LoginAPI
make debug release
# commonapi
cd $BASEDIR/src/external/3rd/library/platform/projects/Session/CommonAPI
make debug release
# base
cd $BASEDIR/src/external/3rd/library/platform/utils/Base/linux
make debug_st release_st
# commodityapi
cd $BASEDIR/src/external/3rd/library/soePlatform/CommodityAPI/linux
make debug release
cp $BASEDIR/src/external/3rd/library/soePlatform/libs/Linux-Debug/libcommodityapi.so $BASEDIR/exe/linux/
cp $BASEDIR/src/external/3rd/library/soePlatform/libs/Linux-Debug/libcommodityapi.so $BASEDIR/dev/linux/
# csassistgameapi
cd $BASEDIR/src/external/3rd/library/soePlatform/CSAssist/projects/CSAssist/CSAssistgameapi
make debug release
echo Copying csassistgameapi
mkdir -p ../../../../libs/Linux-Debug
mkdir -p ../../../../libs/Linux-Release
cp debug/libCSAssistgameapi.a ../../../../libs/Linux-Debug/
cp release/libCSAssistgameapi.a ../../../../libs/Linux-Release/
# note: this includes various other libs that CustomerServiceServer expects to link with, so is not compatible
echo Building monapi
# monapi
cd $BASEDIR/src/external/3rd/library/platform/MonAPI2
make clean
make all
# libOracleDB (CommodityServer)
cd $BASEDIR/src/external/3rd/library/soePlatform/CommodityServer/platform/utils/OracleDB
rm -f *.o
ls *.cpp |sed -e '/\.cpp/s///' -e '/^.*$/s//g++ -g -c -I..\/..\/..\/..\/..\/oracle\/include -I.. &.cpp -o &.o/' >comp.sh
source ./comp.sh
rm -f comp.sh
ar rcs libOracleDB.a *.o
mkdir -p ../../../../libs/Linux-Debug
mv -f libOracleDB.a ../../../../libs/Linux-Debug/libOracleDB.a
# libBase (CommodityServer)
cd $BASEDIR/src/external/3rd/library/soePlatform/CommodityServer/platform/utils/Base
rm -f *.o */*.o
ls *.cpp linux/*.cpp |sed -e '/\.cpp/s///' -e '/^.*$/s//g++ -g -c -Dlinux=1 -D_REENTRANT &.cpp -o &.o/' >comp.sh
source ./comp.sh
rm -f comp.sh
ar rcs libBase.a *.o linux/*.o
mkdir -p ../../../../libs/Linux-Debug
mv -f libBase.a ../../../../libs/Linux-Debug/libBase.a
# Create an empty library.a to solve makefile dependencies on libCSAssistBase.a and libCSAssistUnicode.a
echo > /tmp/empty.cpp
g++ -c -o /tmp/empty.o /tmp/empty.cpp
ar crs /tmp/empty.a /tmp/empty.o
mkdir -p $BASEDIR/src/external/3rd/library/soePlatform/libs/Linux-Debug
cp /tmp/empty.a $BASEDIR/src/external/3rd/library/soePlatform/libs/Linux-Debug/libCSAssistBase.a
cp /tmp/empty.a $BASEDIR/src/external/3rd/library/soePlatform/libs/Linux-Debug/libCSAssistUnicode.a
mkdir -p $BASEDIR/src/external/3rd/library/soePlatform/libs/Linux-Release
cp /tmp/empty.a $BASEDIR/src/external/3rd/library/soePlatform/libs/Linux-Release/libCSAssistBase.a
cp /tmp/empty.a $BASEDIR/src/external/3rd/library/soePlatform/libs/Linux-Release/libCSAssistUnicode.a
# Build CommoditiesServer_d and CommoditiesServer_r
# .. start with local OracleDB library
cd $BASEDIR/src/external/3rd/library/soePlatform/CommodityServer/platform/utils/OracleDB
make all
# .. now do the server
cd ../../..
make all
# Copy CommoditiesServer_* to exe/linux. The normal
# make process copies those from exe/linux to dev/linux.
cp commoditysvr $BASEDIR/exe/linux/CommoditiesServer_d
cp commoditysvr $BASEDIR/exe/linux/CommoditiesServer_r
# Remove the debugging symbols from the release version.
# This save 80+ MB.
strip -g $BASEDIR/exe/linux/CommoditiesServer_r
# Copy Commodities server from exe/linux to dev/linux for the first time. Failure to do this
# will cause the build to break.
cp $BASEDIR/exe/linux/CommoditiesServer_* $BASEDIR/dev/linux
# Build the MonAPI2 library.
cd $BASEDIR/src/external/3rd/library/platform/MonAPI2
./bootstrap
./configure --with-udplibrary=../../udplibrary --prefix=`pwd`
make
make install

168
tools/buildCrcStringTable.pl Executable file
View File

@@ -0,0 +1,168 @@
#!/usr/bin/perl
use warnings;
use strict;
# =====================================================================
my @crctable =
(
hex("0x00000000"), hex("0x04C11DB7"), hex("0x09823B6E"), hex("0x0D4326D9"), hex("0x130476DC"), hex("0x17C56B6B"), hex("0x1A864DB2"), hex("0x1E475005"),
hex("0x2608EDB8"), hex("0x22C9F00F"), hex("0x2F8AD6D6"), hex("0x2B4BCB61"), hex("0x350C9B64"), hex("0x31CD86D3"), hex("0x3C8EA00A"), hex("0x384FBDBD"),
hex("0x4C11DB70"), hex("0x48D0C6C7"), hex("0x4593E01E"), hex("0x4152FDA9"), hex("0x5F15ADAC"), hex("0x5BD4B01B"), hex("0x569796C2"), hex("0x52568B75"),
hex("0x6A1936C8"), hex("0x6ED82B7F"), hex("0x639B0DA6"), hex("0x675A1011"), hex("0x791D4014"), hex("0x7DDC5DA3"), hex("0x709F7B7A"), hex("0x745E66CD"),
hex("0x9823B6E0"), hex("0x9CE2AB57"), hex("0x91A18D8E"), hex("0x95609039"), hex("0x8B27C03C"), hex("0x8FE6DD8B"), hex("0x82A5FB52"), hex("0x8664E6E5"),
hex("0xBE2B5B58"), hex("0xBAEA46EF"), hex("0xB7A96036"), hex("0xB3687D81"), hex("0xAD2F2D84"), hex("0xA9EE3033"), hex("0xA4AD16EA"), hex("0xA06C0B5D"),
hex("0xD4326D90"), hex("0xD0F37027"), hex("0xDDB056FE"), hex("0xD9714B49"), hex("0xC7361B4C"), hex("0xC3F706FB"), hex("0xCEB42022"), hex("0xCA753D95"),
hex("0xF23A8028"), hex("0xF6FB9D9F"), hex("0xFBB8BB46"), hex("0xFF79A6F1"), hex("0xE13EF6F4"), hex("0xE5FFEB43"), hex("0xE8BCCD9A"), hex("0xEC7DD02D"),
hex("0x34867077"), hex("0x30476DC0"), hex("0x3D044B19"), hex("0x39C556AE"), hex("0x278206AB"), hex("0x23431B1C"), hex("0x2E003DC5"), hex("0x2AC12072"),
hex("0x128E9DCF"), hex("0x164F8078"), hex("0x1B0CA6A1"), hex("0x1FCDBB16"), hex("0x018AEB13"), hex("0x054BF6A4"), hex("0x0808D07D"), hex("0x0CC9CDCA"),
hex("0x7897AB07"), hex("0x7C56B6B0"), hex("0x71159069"), hex("0x75D48DDE"), hex("0x6B93DDDB"), hex("0x6F52C06C"), hex("0x6211E6B5"), hex("0x66D0FB02"),
hex("0x5E9F46BF"), hex("0x5A5E5B08"), hex("0x571D7DD1"), hex("0x53DC6066"), hex("0x4D9B3063"), hex("0x495A2DD4"), hex("0x44190B0D"), hex("0x40D816BA"),
hex("0xACA5C697"), hex("0xA864DB20"), hex("0xA527FDF9"), hex("0xA1E6E04E"), hex("0xBFA1B04B"), hex("0xBB60ADFC"), hex("0xB6238B25"), hex("0xB2E29692"),
hex("0x8AAD2B2F"), hex("0x8E6C3698"), hex("0x832F1041"), hex("0x87EE0DF6"), hex("0x99A95DF3"), hex("0x9D684044"), hex("0x902B669D"), hex("0x94EA7B2A"),
hex("0xE0B41DE7"), hex("0xE4750050"), hex("0xE9362689"), hex("0xEDF73B3E"), hex("0xF3B06B3B"), hex("0xF771768C"), hex("0xFA325055"), hex("0xFEF34DE2"),
hex("0xC6BCF05F"), hex("0xC27DEDE8"), hex("0xCF3ECB31"), hex("0xCBFFD686"), hex("0xD5B88683"), hex("0xD1799B34"), hex("0xDC3ABDED"), hex("0xD8FBA05A"),
hex("0x690CE0EE"), hex("0x6DCDFD59"), hex("0x608EDB80"), hex("0x644FC637"), hex("0x7A089632"), hex("0x7EC98B85"), hex("0x738AAD5C"), hex("0x774BB0EB"),
hex("0x4F040D56"), hex("0x4BC510E1"), hex("0x46863638"), hex("0x42472B8F"), hex("0x5C007B8A"), hex("0x58C1663D"), hex("0x558240E4"), hex("0x51435D53"),
hex("0x251D3B9E"), hex("0x21DC2629"), hex("0x2C9F00F0"), hex("0x285E1D47"), hex("0x36194D42"), hex("0x32D850F5"), hex("0x3F9B762C"), hex("0x3B5A6B9B"),
hex("0x0315D626"), hex("0x07D4CB91"), hex("0x0A97ED48"), hex("0x0E56F0FF"), hex("0x1011A0FA"), hex("0x14D0BD4D"), hex("0x19939B94"), hex("0x1D528623"),
hex("0xF12F560E"), hex("0xF5EE4BB9"), hex("0xF8AD6D60"), hex("0xFC6C70D7"), hex("0xE22B20D2"), hex("0xE6EA3D65"), hex("0xEBA91BBC"), hex("0xEF68060B"),
hex("0xD727BBB6"), hex("0xD3E6A601"), hex("0xDEA580D8"), hex("0xDA649D6F"), hex("0xC423CD6A"), hex("0xC0E2D0DD"), hex("0xCDA1F604"), hex("0xC960EBB3"),
hex("0xBD3E8D7E"), hex("0xB9FF90C9"), hex("0xB4BCB610"), hex("0xB07DABA7"), hex("0xAE3AFBA2"), hex("0xAAFBE615"), hex("0xA7B8C0CC"), hex("0xA379DD7B"),
hex("0x9B3660C6"), hex("0x9FF77D71"), hex("0x92B45BA8"), hex("0x9675461F"), hex("0x8832161A"), hex("0x8CF30BAD"), hex("0x81B02D74"), hex("0x857130C3"),
hex("0x5D8A9099"), hex("0x594B8D2E"), hex("0x5408ABF7"), hex("0x50C9B640"), hex("0x4E8EE645"), hex("0x4A4FFBF2"), hex("0x470CDD2B"), hex("0x43CDC09C"),
hex("0x7B827D21"), hex("0x7F436096"), hex("0x7200464F"), hex("0x76C15BF8"), hex("0x68860BFD"), hex("0x6C47164A"), hex("0x61043093"), hex("0x65C52D24"),
hex("0x119B4BE9"), hex("0x155A565E"), hex("0x18197087"), hex("0x1CD86D30"), hex("0x029F3D35"), hex("0x065E2082"), hex("0x0B1D065B"), hex("0x0FDC1BEC"),
hex("0x3793A651"), hex("0x3352BBE6"), hex("0x3E119D3F"), hex("0x3AD08088"), hex("0x2497D08D"), hex("0x2056CD3A"), hex("0x2D15EBE3"), hex("0x29D4F654"),
hex("0xC5A92679"), hex("0xC1683BCE"), hex("0xCC2B1D17"), hex("0xC8EA00A0"), hex("0xD6AD50A5"), hex("0xD26C4D12"), hex("0xDF2F6BCB"), hex("0xDBEE767C"),
hex("0xE3A1CBC1"), hex("0xE760D676"), hex("0xEA23F0AF"), hex("0xEEE2ED18"), hex("0xF0A5BD1D"), hex("0xF464A0AA"), hex("0xF9278673"), hex("0xFDE69BC4"),
hex("0x89B8FD09"), hex("0x8D79E0BE"), hex("0x803AC667"), hex("0x84FBDBD0"), hex("0x9ABC8BD5"), hex("0x9E7D9662"), hex("0x933EB0BB"), hex("0x97FFAD0C"),
hex("0xAFB010B1"), hex("0xAB710D06"), hex("0xA6322BDF"), hex("0xA2F33668"), hex("0xBCB4666D"), hex("0xB8757BDA"), hex("0xB5365D03"), hex("0xB1F740B4")
);
my %crc;
my %offset;
my $offset = 0;
# =====================================================================
sub crc
{
use integer;
my $string = $_[0];
return 0 if ($string eq "");
my $crc_init = hex("0xffffffff") & 0xffffffff;
my $crc = $crc_init;
foreach (split(//, $string))
{
$crc = ($crctable[(($crc>>24) ^ ord($_)) & 255] ^ ($crc << 8) & 0xffffffff);
}
return $crc ^ $crc_init & 0xffffffff;
}
# =====================================================================
die "usage: buildCrcStringTable.pl [-t tabFileName.ext] outputFileName.ext [stringFile...]\n" .
"-t : generate tab delimited output file as well\n" .
"If the output file name extension is .mif, then the text mif file will be generated.\n" .
"Otherwise, the binary IFF data will be written.\n" if (@ARGV < 1 || $ARGV[0] =~ /^[\/-][h\?]$/);
my $outputFileName = shift;
my $tab = 0;
my $tabFileName = "";
if ($outputFileName eq "-t")
{
$tab = 1;
$tabFileName = shift;
$outputFileName = shift;
}
while (<>)
{
chomp();
if ($_ ne "")
{
my $crc = sprintf("0x%08x", crc($_));
die "crc string clash for $crc:\n\t$crc{$crc}\n\t$_\n" if (defined($crc{$crc}) && $_ ne $crc{$crc});
$crc{$crc} = $_;
}
}
open(OUTPUT, "> tempfile") || die "could not open tempfile\n";
my $old = select(OUTPUT);
print "form \"CSTB\"\n";
print "{\n";
print "\tform \"0000\"\n";
print "\t{\n";
print "\t\tchunk \"DATA\"\n";
print "\t\t{\n";
print "\t\t\tint32 ", scalar(keys(%crc)), "\n";
print "\t\t}\n";
print "\n";
print "\t\tchunk \"CRCT\"\n";
print "\t\t{\n";
foreach (sort keys %crc)
{
print "\t\t\tuint32 ", $_, "\n";
$offset{$_} = $offset;
$offset += length($crc{$_}) + 1;
}
print "\t\t}\n";
print "\n";
print "\t\tchunk \"STRT\"\n";
print "\t\t{\n";
foreach (sort keys %crc)
{
print "\t\t\tint32 ", $offset{$_}, "\n";
}
print "\t\t}\n";
print "\n";
print "\t\tchunk \"STNG\"\n";
print "\t\t{\n";
foreach (sort keys %crc)
{
print "\t\t\tcstring \"", $crc{$_}, "\" /* ", $_, " */\n";
}
print "\t\t}\n";
print "\t}\n";
print "}\n";
select $old;
close(OUTPUT);
if ($outputFileName =~ /\.mif/)
{
rename("tempfile", $outputFileName);
}
else
{
print $outputFileName, "\n";
system("Miff -i tempfile -o $outputFileName");
unlink("tempfile");
}
if ($tab)
{
open(OUTPUT, ">" . $tabFileName) || die "could not open $tabFileName\n";
foreach (sort keys %crc)
{
print OUTPUT $_, "\t", $crc{$_}, "\n";
}
close(OUTPUT);
}

View File

@@ -0,0 +1,138 @@
use strict;
use warnings;
my $branch;
my $all = "";
my $only = "";
# =====================================================================
sub perforceWhere
{
# find out where a perforce file resides on the local machine
my $result;
{
open(P4, "p4 where $_[0] |");
while ( <P4> )
{
next if ( /^-/ );
chomp;
my @where = split;
$result = $where[2];
}
close(P4);
}
return $result;
}
sub usage
{
die "usage: buildObjectTemplateCrcStringTables [--local|--all|--only <changelist#>] <current|test|live|x1|x2|ep3|demo|s#>\n" .
"\t--local : include pending files only from the local client\n" .
"\t--all : include pending files from all clients\n" .
"\t--only <changelist#> : include pending files only from <changelist#>\n" .
"\tif no option is provided, --local is assumed.\n";
}
# =====================================================================
sub perforceGatherAndPrune
{
local $_;
my %files;
foreach my $spec (@_)
{
open(P4, "p4 files $spec/... |");
while (<P4>)
{
chomp;
next if (/ delete /)/
s%//depot/swg/$branch/data/sku\.0/sys\.(shared|server)/compiled/game/%%;
s/#.*//;
$files{$_} = 1;
}
close(P4);
open(P4, "p4 opened " . $all . " " . $only . " $spec/... |");
while (<P4>)
{
chomp;
s%//depot/swg/$branch/data/sku\.0/sys\.(shared|server)/compiled/game/%%;
s/#.*//;
$files{$_} = 1;
}
close(P4);
}
return sort keys %files;
}
# =====================================================================
if ($#ARGV == 1 || $#ARGV == 2)
{
if ($ARGV[0] eq "--local")
{
$all = "";
}
elsif ($ARGV[0] eq "--all")
{
$all = "-a";
}
elsif ($ARGV[0] eq "--only" && $#ARGV == 2)
{
$all = "";
$only = "-c " . $ARGV[1];
shift;
}
else
{
usage();
}
shift;
}
usage() unless (defined($ARGV[0]) && $ARGV[0] =~ m%^(current|test|stage|live|x1|x2|ep3|demo|s\d+)$%);
$branch = $ARGV[0];
my $buildCrcStringTable = perforceWhere("//depot/swg/$branch/tools/buildCrcStringTable.pl");
{
my $tab = perforceWhere("//depot/swg/$branch/dsrc/sku.0/sys.client/built/game/misc/object_template_crc_string_table.tab");
my $output = perforceWhere("//depot/swg/$branch/data/sku.0/sys.client/built/game/misc/object_template_crc_string_table.iff");
print "building client object template strings:\n\t$tab\n\t$output\n";
system("p4 edit $tab $output");
my @files = perforceGatherAndPrune(
"//depot/swg/$branch/data/sku.0/sys.shared/compiled/game/object",
"//depot/swg/$branch/data/sku.0/sys.server/compiled/game/object/creature/player");
open(B, "| perl $buildCrcStringTable -t $tab $output");
foreach (@files)
{
print B $_, "\n";
}
close(B);
}
{
my $tab = perforceWhere("//depot/swg/$branch/dsrc/sku.0/sys.server/built/game/misc/object_template_crc_string_table.tab");
my $output = perforceWhere("//depot/swg/$branch/data/sku.0/sys.server/built/game/misc/object_template_crc_string_table.iff");
print "building server object template strings:\n\t$tab\n\t$output\n";
system("p4 edit $tab $output");
my @files = perforceGatherAndPrune(
"//depot/swg/$branch/data/sku.0/sys.shared/compiled/game/object",
"//depot/swg/$branch/data/sku.0/sys.server/compiled/game/object");
open(B, "| perl $buildCrcStringTable -t $tab $output");
foreach (@files)
{
print B $_, "\n";
}
close(B);
}

View File

@@ -0,0 +1,120 @@
#!/usr/bin/perl
use strict;
use warnings;
my $branch;
my $all = "";
my $only = "";
# =====================================================================
sub perforceWhere
{
# find out where a perforce file resides on the local machine
my $result;
{
open(P4, "p4 where $_[0] |");
while ( <P4> )
{
next if ( /^-/ );
chomp;
my @where = split;
$result = $where[2];
}
close(P4);
}
return $result;
}
sub usage
{
die "usage: buildQuestCrcStringTables [--local|--all|--only <changelist#>] <current|stage|test|live|x1|x2|ep3|demo|s#>\n" .
"\t--local : include pending files only from the local client\n" .
"\t--all : include pending files from all clients\n" .
"\t--only <changelist#> : include pending files only from <changelist#>\n" .
"\tif no option is provided, --local is assumed.\n";
}
# =====================================================================
sub perforceGatherAndPrune
{
local $_;
my %files;
foreach my $spec (@_)
{
open(P4, "p4 files $spec/... |");
while (<P4>)
{
chomp;
next if (/ delete /)/
s%//depot/swg/$branch/data/sku\.0/sys\.(shared|server)/compiled/game/datatables/questlist/%%;
s/\.iff//;
s/#.*//;
$files{$_} = 1;
}
close(P4);
open(P4, "p4 opened " . $all . " " . $only . " $spec/... |");
while (<P4>)
{
chomp;
s%//depot/swg/$branch/data/sku\.0/sys\.(shared|server)/compiled/game/datatables/questlist/%%;
s/\.iff//;
s/#.*//;
$files{$_} = 1;
}
close(P4);
}
return sort keys %files;
}
# =====================================================================
if ($#ARGV == 1 || $#ARGV == 2)
{
if ($ARGV[0] eq "--local")
{
$all = "";
}
elsif ($ARGV[0] eq "--all")
{
$all = "-a";
}
elsif ($ARGV[0] eq "--only" && $#ARGV == 2)
{
$all = "";
$only = "-c " . $ARGV[1];
shift;
}
else
{
usage();
}
shift;
}
usage() unless (defined($ARGV[0]) && $ARGV[0] =~ m%^(current|stage|test|live|x1|x2|ep3|demo|s\d+)$%);
$branch = $ARGV[0];
{
my $tab = perforceWhere("//depot/swg/$branch/dsrc/sku.0/sys.shared/built/game/misc/quest_crc_string_table.tab");
my $output = perforceWhere("//depot/swg/$branch/data/sku.0/sys.shared/built/game/misc/quest_crc_string_table.iff");
print "building quest template strings:\n\t$tab\n\t$output\n";
system("p4 edit $tab $output");
my @files = perforceGatherAndPrune("//depot/swg/$branch/data/sku.0/sys.shared/compiled/game/datatables/questlist");
open(B, "| perl buildCrcStringTable.pl -t $tab $output");
foreach (@files)
{
print B $_, "\n";
}
close(B);
}

View File

@@ -0,0 +1,53 @@
use Cwd;
use strict;
use ConfigFile;
use Perforce;
use TreeFile;
my $debug = 1;
my $justPrint = 0;
# Grab branch from commandline, default to current.
my $branch = shift;
$branch = 'current' if !defined($branch);
print "branch: $branch\n" if $debug;
# Grab p4 changelist number for treefile.
my $p4ChangelistOutput = `p4 changes -m1 //depot/swg/$branch/data/...#have`;
my $p4ChangelistNumber = $1 if ($p4ChangelistOutput =~ m/\s*Change\s*(\d+)/) || die "Failed to find changelist number";
print "changelist number: $p4ChangelistNumber\n" if $debug;
# Construct config file common.cfg file location. We just need the loose-file treefile paths.
my $configPathName = Perforce::findOnDiskFileName("//depot/swg/$branch/exe/win32/client.cfg");
$configPathName =~ s!\\!/!g;
print "config file pathname: [$configPathName]\n" if $debug;
# Setup ConfigFile.
ConfigFile::processConfigFile($configPathName) if !$justPrint;
# Build treefile map pathname, places it in current directory.
my $treefileLookupPathName = getcwd();
$treefileLookupPathName .= '/' if !($treefileLookupPathName =~ m!/$!);
$treefileLookupPathName .= "treefile-xlat-$branch-$p4ChangelistNumber.dat";
print "treefile lookup pathname: [$treefileLookupPathName]\n" if $debug;
# Open treefile map filehandle.
my $fileHandle;
die "could not open treefile handle: $!" if !($justPrint || open($fileHandle, "> " . $treefileLookupPathName));
# Construct rooted directory path for relative treefile searchpath locations.
# Just chop off everything after and including the last slash in the config pathname.
my $rootedBaseSearchPath = $configPathName;
$rootedBaseSearchPath =~ s!/[^/]+$!!;
print "treefile rooted base searchpath: [$rootedBaseSearchPath]\n" if $debug;
# Build the TreeFile map file.
TreeFile::buildFileLookupTable(1, $rootedBaseSearchPath) if !$justPrint;
# Save the TreeFile map file.
TreeFile::saveFileLookupTable($fileHandle) if !$justPrint;
# Close the map file.
die "could not close treefile handle: $!" if !($justPrint || close($fileHandle));
print "Done.\n" if $debug;

691
tools/build_bootleg_linux.pl Executable file
View File

@@ -0,0 +1,691 @@
#! /usr/bin/perl
# ======================================================================
# ======================================================================
use warnings;
use strict;
use Socket;
use Getopt::Long;
use File::Copy;
# ======================================================================
# Constants
# ======================================================================
use constant START_BOOTLEG_TEST => "A";
use constant END_COMMUNICATION => "B";
use constant SUCCESSFUL_TEST => "C";
use constant UNSUCCESSFUL_TEST => "D";
use constant SERVER_READY => "E";
use constant BOOTLEG_MISMATCH => "F";
use constant CLIENT_KILL => "G";
use constant CLIENT_OK => "H";
use constant GOT_BUILD_CLUSTER_VERSION => "I";
use constant FAILED_GETTING_BUILD_CLUSTER_VERSION => "J";
use constant START_UPKEEP => "K";
use constant START_BOOTLEG_SEND => "L";
use constant BOOTLEG_SEND_DIRECTORY => "M";
use constant BOOTLEG_SEND_FILE => "N";
use constant END_BOOTLEG_SEND => "O";
use constant START_EMAIL => "P";
# ======================================================================
# Globals
# ======================================================================
my $name = $0;
$name =~ s/^(.*)\\//;
my $depotdir = "/swg";
my $bootlegdir = "/swg/bootlegs";
my $logfile = "build_bootleg.log";
my $win32machine = "64.37.133.173";
my $port = "21498";
my $emailRecipients = "vthakkar\@soe.sony.com";
my $waittime = "180";
my $branch = "";
my $oldbootleg = "";
my $newbootleg = "";
my $loginpid;
my $taskpid;
my @steps = (0, 0, 0, 0, 0, 0, 0, 0);
# ======================================================================
# Subroutines
# ======================================================================
sub usage
{
print "\n\t$name <optional parameters> <branch>\n\n".
"\tOptional parameters:\n\n".
"\t\t--no_script\t: Don't do a script recompile\n".
"\t\t--no_build\t: Don't build a new bootleg\n".
"\t\t--no_patch\t: Don't create a patchtree file\n".
"\t\t--no_send\t: Don't send build / patch results to win32 machine\n".
"\t\t--no_install\t: Don't install newest bootleg\n".
"\t\t--no_test\t: Don't perform test on bootleg\n".
"\t\t--no_email\t: Don't send email about results\n".
"\t\t--no_upkeep\t: Don't perform upkeep on bootleg directories\n".
"\n\tWarning: Some options depend on others, some combinations may not work.\n";
die "\n";
}
sub writelog
{
my $message = shift @_;
chomp $message;
my ($sec, $min, $hr, $day, $mon, $yr) = localtime time;
my $timestamp = sprintf "%4s-%02s-%02s\t%02s:%02s:%02s", ($yr + 1900), ($mon + 1), $day, $hr, $min, $sec;
print LOG join("\t", $timestamp, $message), "\n";
}
sub fatal
{
my $message = shift @_;
print "Fatal error running: $message\n";
writelog("Fatal error running: $message");
close(LOG);
die;
}
sub unbuffer
{
my $oldSelect = select($_[0]);
$| = 1;
select($oldSelect);
}
sub unbufferReadline
{
my ($fh) = @_;
my $buffer;
my $return = "";
while(sysread($fh, $buffer, 1))
{
$return .= $buffer;
last if($buffer eq "\n");
}
return $return;
}
sub perforceWhere
{
local $_;
# find out where a perforce file resides on the local machine
my $result;
{
open(P4, "p4 where $_[0] |");
$_ = <P4>;
chomp;
my @where = split;
$result = $where[2];
close(P4);
}
return $result;
}
sub openClientSocket
{
socket(SOCKET, PF_INET, SOCK_STREAM, getprotobyname('tcp')) || closeServer("socket failed\n");
{
my $destination = inet_aton($win32machine) || closeServer("inet_aton failed\n");
my $paddr = sockaddr_in($port, $destination);
connect(SOCKET, $paddr) || closeServer("connect failed\n");
# unbuffer the socket
my $oldSelect = select(SOCKET);
$| = 1;
select($oldSelect);
# put the socket into binary mode
binmode SOCKET;
}
}
sub buildBootleg
{
my $win32complete = 0;
my $linuxcomplete = 0;
print "Building bootleg...\n";
writelog("Building bootleg");
open(LINUXBUILD, "perl ${depotdir}/swg/current/tools/build_script_linux_new.pl $branch -bootleg -incrediBuild 2>&1 |") or fatal "Error running build_script_linux.pl\n";
while(<LINUXBUILD>)
{
print;
writelog($_);
$newbootleg = $1 if(/^Syncing to $branch\@(\d+)/);
$win32complete = 1 if(/^Windows build returned 0/);
$linuxcomplete = 1 if(/^Linux build returned 0/);
}
close(LINUXBUILD);
print "linux build incomplete\n" if(!$linuxcomplete);
print "windows build incomplete\n" if(!$win32complete);
print "Completed building bootleg $newbootleg.\n\n" if($win32complete && $linuxcomplete);
writelog("Bootleg: $newbootleg, Linux complete: $linuxcomplete, Windows complete: $win32complete");
($win32complete && $linuxcomplete) ? return 1 : return 0;
}
sub buildPatchTree
{
my $patch_tree_complete = 0;
my $patch_changelist = 0;
print "Building patch tree...\n";
writelog("Building patch tree");
mkdir "$bootlegdir/$branch/$newbootleg/patch" || fatal "mkdir for patchtree failed";
open(PATCHTREE, "perl ${depotdir}/swg/current/tools/CheckPatchTreeSize.pl --sync --changelist=$newbootleg --save_treefile=$bootlegdir/$branch/$newbootleg/patch/bootlegpatch.tre |") or fatal "Error running CheckPatchTreeSize.pl\n";
while(<PATCHTREE>)
{
print;
writelog($_);
$patch_changelist = $1 if(/^Most recent final manifest at revision \d+, patch \d+, changelist (\d+)/);
$patch_tree_complete = 1 if(/^Size of \.tre is: \d+$/);
}
close(PATCHTREE);
move "$bootlegdir/$branch/$newbootleg/patch/bootlegpatch.tre", "$bootlegdir/$branch/$newbootleg/patch/bootleg_${patch_changelist}_${newbootleg}.tre";
print "Patch tree build incomplete.\n\n" if(!$patch_tree_complete);
print "Patch tree build complete.\n\n" if($patch_tree_complete);
writelog("Patch Tree complete: $patch_tree_complete");
return $patch_tree_complete;
}
sub sendBootleg
{
print "Sending bootleg / patch to win32 machine...\n";
writelog("Sending bootleg / patch to win32 machine...");
openClientSocket();
print SOCKET START_BOOTLEG_SEND;
print SOCKET pack("N", length $branch);
print SOCKET $branch;
print SOCKET pack("N", $newbootleg);
# Build an array of what directories to send over
my @directories;
push @directories, "patch" if(-d "$bootlegdir/$branch/$newbootleg/patch");
push @directories, "servers" if(-d "$bootlegdir/$branch/$newbootleg/servers");
while(@directories = sort @directories)
{
my $dir = shift @directories;
# Tell the windows machine to get a new directory
print SOCKET BOOTLEG_SEND_DIRECTORY;
print SOCKET pack("N", length $dir);
print SOCKET $dir;
opendir DH, "$bootlegdir/$branch/$newbootleg/$dir" || die "could not open directory\n";
foreach my $fileName (sort readdir DH)
{
next if($fileName eq "." || $fileName eq "..");
push @directories, "$dir/$fileName" if(-d "$bootlegdir/$branch/$newbootleg/$dir/$fileName");
next if(!-f "$bootlegdir/$branch/$newbootleg/$dir/$fileName");
my $fileSize = -s "$bootlegdir/$branch/$newbootleg/$dir/$fileName";
print "Sending file $fileName ($fileSize bytes)\n";
writelog("Sending file $fileName ($fileSize bytes)");
print SOCKET BOOTLEG_SEND_FILE;
print SOCKET pack("NN", length $fileName, $fileSize);
print SOCKET $fileName;
open(F, "<$bootlegdir/$branch/$newbootleg/$dir/$fileName");
binmode(F);
while ($fileSize)
{
my $buffer;
my $readSize = 16 * 1024;
$readSize = $fileSize if ($fileSize < $readSize);
my $readResult = read(F, $buffer, $readSize);
die "unexpected end of file" if (!defined($readResult));
die "did not read what we expected to" if ($readResult != $readSize);
print SOCKET $buffer;
$fileSize -= $readResult;
}
die "copied all the bytes but not at EOF" if (!eof(F));
close(F);
}
closedir DH;
}
print SOCKET END_BOOTLEG_SEND;
print "Finished sending to win32 machine.\n";
writelog("Finished sending to win32 machine.");
close(SOCKET);
return 1;
}
sub installBootleg
{
print "Installing bootleg...\n";
writelog("Installing bootleg");
open(INSTALL, "perl " . perforceWhere("//depot/swg/current/tools/InstallBootleg.pl") . " --list --force_newest --server_only --install_as_build_cluster $branch |") or fatal "Error running InstallBootleg.pl\n";
my $complete = 0;
while(<INSTALL>)
{
print;
writelog($_);
$complete = 1 if(/^Update complete\./);
$oldbootleg = $1 if($oldbootleg eq "" && /^\d+\s+(\d+)\s+blessed/);
$newbootleg = $1 if(/^Updating to build: (\d+)/);
}
close(INSTALL);
print "Bootleg installation incomplete\n" if(!$complete);
print "Completed installing bootleg.\n\n" if($complete);
writelog("OldBootleg: $oldbootleg, InstallBootleg complete: $complete");
return $complete;
}
sub closeServer
{
print "Fatal Error: Killing forked processes\n";
endServer();
fatal $_[0];
}
sub startServer
{
my $loginServer = "debug/LoginServer";
my $taskManager = "debug/TaskManager";
writelog("Starting Server");
my $serverdir = perforceWhere("//depot/swg/$branch/bootleg/linux/fakefile");
$serverdir =~ s/fakefile$//;
chdir($serverdir) || fatal "Cannot change directory to $serverdir\n";
print "Starting up server...\n";
$loginpid = open(LOGINSERVER, "$loginServer -- \@loginServer.cfg 2>&1 |") or closeServer("Can't open LoginServer\n");
binmode LOGINSERVER;
while(<LOGINSERVER>)
{
writelog("LoginServer: $_") if(/\S+/);
last if(/^Log observer setup/);
}
$taskpid = open(TASKMANAGER, "$taskManager -- \@taskmanager.cfg 2>&1 |") or closeServer("Can't open TaskManager\n");
binmode TASKMANAGER;
while(<TASKMANAGER>)
{
writelog("TaskManager: $_") if(/\S+/);
last if(/^Preload finished on all planets/);
}
}
sub endServer
{
writelog("Ending Server");
print "Shutting down server.\n";
kill 1, $taskpid if(defined $taskpid);
kill 1, $loginpid if(defined $loginpid);
system("killall CommoditiesServer");
system("killall ChatServer");
close(TASKMANAGER);
close(LOGINSERVER);
}
sub startClient
{
writelog("Starting Client");
print "Starting up client...\n";
openClientSocket();
print SOCKET START_BOOTLEG_TEST;
print SOCKET pack("N", length $branch);
print SOCKET $branch;
}
sub endClient
{
writelog("Ending Client");
print SOCKET CLIENT_KILL;
print "Shutting down client.\n";
close(SOCKET);
}
sub checkResponses
{
writelog("Verifying server and client responses");
my $loginsuccess = 0;
my $tasksuccess = 0;
my $buffer;
print "Verifying client and server have same bootleg installation.\n";
read(SOCKET, $buffer, 4) == 4 or fatal "Error reading from win32 machine\n";
my $clientbootleg = unpack("N", $buffer);
if($clientbootleg ne $newbootleg)
{
writelog("Mismatch in client / server bootlegs - client: $clientbootleg, server: $newbootleg");
print "Mismatch in client / server bootlegs - client: $clientbootleg, server: $newbootleg\n";
print SOCKET BOOTLEG_MISMATCH;
return 0;
}
print "Both client and server have bootleg $newbootleg installed\n";
writelog("Both client and server have bootleg $newbootleg installed");
print SOCKET SERVER_READY;
my $starttime = time;
writelog("Beginning test with client - timeout of $waittime seconds");
# used to create non-blocking reading of both filehandles
while(1)
{
my $rin = '';
my $rout;
my $line;
vec($rin, fileno(LOGINSERVER), 1) = 1;
vec($rin, fileno(TASKMANAGER), 1) = 1;
if(select($rout=$rin, undef, undef, 0))
{
if (vec($rout, fileno(LOGINSERVER), 1))
{
$line = unbufferReadline(\*LOGINSERVER);
if(defined $line)
{
writelog("LoginServer: $line") if($line =~ /\S+/);
++$loginsuccess if($loginsuccess == 0 && $line =~ /^connection opened for service on port \d+/);
++$loginsuccess if($loginsuccess == 1 && $line =~ /^Encrypting with key:/);
++$loginsuccess if($loginsuccess == 2 && $line =~ /^Client connected\. Station Id: \d+, Username: bootleg/);
++$loginsuccess if($loginsuccess == 3 && $line =~ /^Client \d+ disconnected/);
last if ($line =~ /ERROR/ or $line =~ /FATAL/);
}
}
if (vec($rout, fileno(TASKMANAGER), 1))
{
$line = unbufferReadline(\*TASKMANAGER);
if(defined $line)
{
writelog("TaskManager: $line") if($line =~ /\S+/);
++$tasksuccess if($tasksuccess == 0 && $line =~ /^connection opened for service on port \d+/);
++$tasksuccess if($tasksuccess == 1 && $line =~ /^Opened connection with client/);
++$tasksuccess if($tasksuccess == 2 && $line =~ /^Recieved ClientIdMsg/);
++$tasksuccess if($tasksuccess == 3 && $line =~ /^Decrypting with key: /);
++$tasksuccess if($tasksuccess == 4 && $line =~ /^succeeded/);
++$tasksuccess if($tasksuccess == 5 && $line =~ /^ValidateAccountMessage/);
++$tasksuccess if($tasksuccess == 6 && $line =~ /^ValidateAccountReplyMessage/);
++$tasksuccess if($tasksuccess == 7 && $line =~ /^Permissions for \d+:/);
++$tasksuccess if($tasksuccess == 8 && $line =~ /canLogin/);
++$tasksuccess if($tasksuccess == 9 && $line =~ /canCreateRegularCharacter/);
++$tasksuccess if($tasksuccess == 10 && $line =~ /^Recvd SelectCharacter message for \d+/);
++$tasksuccess if($tasksuccess == 11 && $line =~ /^Got ValidateCharacterForLoginMessage acct \d+, character \d+/);
++$tasksuccess if($tasksuccess == 12 && $line =~ /^Pending character \d+ is logging in or dropping/);
last if ($line =~ /ERROR/ or $line =~ /FATAL/);
}
}
}
return 0 if((time - $starttime) > $waittime);
last if($loginsuccess == 4 && $tasksuccess == 13);
}
writelog("LoginServer success: $loginsuccess/4, Taskmanager success: $tasksuccess/13");
return 0 if($loginsuccess != 4 || $tasksuccess != 13);
# Tell win32 machine that the client is ok (don't need to kill it)
print SOCKET CLIENT_OK;
read(SOCKET, $buffer, 1) == 1 or fatal "Error reading from win32 machine\n";
my $clientsuccess = 0;
$clientsuccess = 1 if($buffer eq SUCCESSFUL_TEST);
writelog("Client success: $clientsuccess/1");
return 0 if($clientsuccess != 1);
return 1;
}
sub testBootleg
{
print "Testing bootleg...\n";
writelog("Testing bootleg");
my $test = 0;
startServer();
startClient();
$test = checkResponses();
endServer();
endClient();
fatal "Test for bootleg $newbootleg unsuccessful\n" if(!$test);
print "Testing successful.\n\n";
writelog("Test for bootleg successful: $test");
open(BLESS, ">$bootlegdir/$branch/$newbootleg/blessed.txt");
close(BLESS);
return 1;
}
sub email
{
return 0 if($newbootleg eq "");
# Get old bootleg if we don't know it
if($oldbootleg eq "")
{
openClientSocket();
print SOCKET START_EMAIL;
# Tell the client which bootleg to ignore
print SOCKET pack("N", length $newbootleg);
print SOCKET $newbootleg;
my $buffer;
return 0 if(read(SOCKET, $buffer, 4) != 4);
my $oldBootlegLength = unpack("N", $buffer);
return 0 if($oldBootlegLength == 0);
return 0 if(read(SOCKET, $oldbootleg, $oldBootlegLength) != $oldBootlegLength);
close(SOCKET);
}
print "Emailing about changes from bootleg $oldbootleg to $newbootleg...\n";
writelog("Emailing changes from $oldbootleg to $newbootleg");
return 0 if($oldbootleg eq "");
open(EMAIL, "| mail -s \"[bootleg] $branch.$newbootleg.0 is up\" $emailRecipients");
print EMAIL "${bootlegdir}/\n".
"\n-Vijay\n\n";
print EMAIL "Changes between $oldbootleg and $newbootleg\n";
open(CHANGES, "perl ${depotdir}/swg/current/tools/BuildChanges.pl -i //depot/swg/$branch/... $oldbootleg $newbootleg |");
while(<CHANGES>)
{
next if(/^Change (\d+) on/ || /^\[(public|internal)\]/ || /^\n/ || /.?none.?/i || /n(\/|\.)a/i || /^---/ || /ignoring script recompile/i);
s/^\s*-?\s*//;
print EMAIL "\t- $_";
}
close(CHANGES);
print "Completed emailing.\n\n";
writelog("Completed emailing.");
return 1;
}
sub upkeep
{
my $buffer;
print "Performing upkeep on bootleg directory for $branch...\n";
writelog("Performing upkeep on bootleg directory for $branch...");
openClientSocket();
print SOCKET START_UPKEEP;
print SOCKET pack("N", length $branch);
print SOCKET $branch;
return 0 if(read(SOCKET, $buffer, 1) != 1);
if($buffer eq FAILED_GETTING_BUILD_CLUSTER_VERSION)
{
print "Failed getting build cluster version\n";
writelog("Failed getting build cluster version");
return 0;
}
elsif($buffer eq GOT_BUILD_CLUSTER_VERSION)
{
return 0 if(read(SOCKET, $buffer, 4) != 4);
my $buildClusterBootleg = unpack("N", $buffer);
print "Build cluster bootleg version is $buildClusterBootleg\n";
writelog("Build cluster bootleg version is $buildClusterBootleg");
}
else
{
print "Got incorrect return from win32 machine\n";
writelog("Got incorrect return from win32 machine.");
return 0;
}
while(1)
{
return 0 if(read(SOCKET, $buffer, 4) != 4);
my $bootlegVer = unpack("N", $buffer);
last if($bootlegVer == 0);
print "Removed bootleg $branch/$bootlegVer.\n";
writelog("Removed bootleg $branch/$bootlegVer.");
}
while(1)
{
return 0 if(read(SOCKET, $buffer, 4) != 4);
my $pdbFileLength = unpack("N", $buffer);
last if($pdbFileLength == 0);
return 0 if(read(SOCKET, $buffer, $pdbFileLength) != $pdbFileLength);
print "Removed pdb file $buffer.\n";
writelog("Removed pdb file $buffer.");
}
close(SOCKET);
}
sub submitOpenFiles
{
local $_;
my @files;
open(P4, "p4 -ztag opened -c default |");
while (<P4>)
{
chomp;
push (@files, $_) if (s/^\.\.\. depotFile //);
}
close(P4);
my $tmpfile = "submit.tmp";
# submit all the open files
open(TMP, ">" . $tmpfile);
print TMP "Change:\tnew\n";
print TMP "\nDescription:\n";
foreach (@_)
{
print TMP "\t", $_, "\n";
}
print TMP "\nFiles:\n";
foreach (@files)
{
print TMP "\t", $_, "\n";
}
close(TMP);
my $result = system("p4 submit -i < $tmpfile");
fatal "p4 submit failed" if ($result != 0);
unlink($tmpfile);
}
sub scriptRecompile
{
print "Recompiling scripts...\n";
writelog("Syncing perforce for script recompile...");
system("p4 sync //depot/swg/$branch/...") == 0 || return 0;
writelog("Sync perforce complete.");
writelog("Recompiling scripts...");
my $result = system("perl ${depotdir}/swg/current/tools/recompileAllScripts.pl $branch");
writelog("Recompile scripts returned $result (success = 0)");
if ($result != 0)
{
my $attach = "";
$attach .= " -a pythonPreprocessorStderr.log" if (-s "pythonPreprocessorStderr.log");
$attach .= " -a javac.log" if (-s "javac.log");
system("mutt -s \"[BUILDLOG $branch] script recompile failed, errors attached\" $attach $emailRecipients < /dev/null");
system("p4 revert -c default //depot/... > /dev/null");
return 0;
}
system("p4 revert -a > /dev/null");
submitOpenFiles("[automated]", "Script recompile for bootleg build");
print "Recompile scripts successful.\n";
return 1;
}
# ======================================================================
# Main
# ======================================================================
usage() if(!GetOptions('no_script' => \$steps[0], 'no_build' => \$steps[1], 'no_patch' => \$steps[2], 'no_send' => \$steps[3], 'no_install' => \$steps[4], 'no_test' => \$steps[5], 'no_email' => \$steps[6], 'no_upkeep' => \$steps[7]));
usage() if(@ARGV != 1);
# open the log file
open(LOG, ">>$logfile") || die "Could not open $logfile\n";
unbuffer(\*LOG);
$branch = shift;
print "Beginning bootleg build for branch $branch\n";
writelog("Beginning bootleg build for branch $branch");
scriptRecompile() || fatal "scriptRecompile" if(!$steps[0]);
buildBootleg() || fatal "build" if(!$steps[1]);
buildPatchTree() || fatal "buildPatchTree" if(!$steps[2]);
sendBootleg() || fatal "sendBootleg" if(!$steps[3]);
installBootleg() || fatal "installBootleg" if(!$steps[4]);
testBootleg() || fatal "testBootleg" if(!$steps[5]);
email() || fatal "email" if(!$steps[6]);
upkeep() || fatal "upkeep" if(!$steps[7]);
print "Build of bootleg $newbootleg complete.\n";
writelog("Build of bootleg $newbootleg complete");
close(LOG);

435
tools/build_bootleg_win32.pl Executable file
View File

@@ -0,0 +1,435 @@
#! /usr/bin/perl
# ======================================================================
# ======================================================================
use warnings;
use strict;
use Socket;
# ======================================================================
# Constants
# ======================================================================
use constant START_BOOTLEG_TEST => "A";
use constant END_COMMUNICATION => "B";
use constant SUCCESSFUL_TEST => "C";
use constant UNSUCCESSFUL_TEST => "D";
use constant SERVER_READY => "E";
use constant BOOTLEG_MISMATCH => "F";
use constant CLIENT_KILL => "G";
use constant CLIENT_OK => "H";
use constant GOT_BUILD_CLUSTER_VERSION => "I";
use constant FAILED_GETTING_BUILD_CLUSTER_VERSION => "J";
use constant START_UPKEEP => "K";
use constant START_BOOTLEG_SEND => "L";
use constant BOOTLEG_SEND_DIRECTORY => "M";
use constant BOOTLEG_SEND_FILE => "N";
use constant END_BOOTLEG_SEND => "O";
use constant START_EMAIL => "P";
# ======================================================================
# Globals
# ======================================================================
my $name = $0;
$name =~ s/^(.*)\\//;
my $branch;
my $numbootlegs = 7;
my $pdbtime = 14;
my $bootlegnum = "";
my $waittime = "60";
my $port = "21498";
my $build_cluster = "lin-vthakkar.station.sony.com";
my $candela = "p:";
# ======================================================================
# Subroutines
# ======================================================================
sub usage
{
die "\n\t$name\n\n";
}
sub perforceWhere
{
local $_;
# find out where a perforce file resides on the local machine
my $result;
{
open(P4, "p4 where $_[0] |");
$_ = <P4>;
chomp;
my @where = split;
$result = $where[2];
close(P4);
}
return $result;
}
sub reloop
{
print STDERR "Error with: $_[0]\n" if(defined $_[0]);
print STDERR "Exiting this connection\n";
goto FAIL;
}
sub installBootleg
{
print "Installing bootleg...\n";
open(INSTALL, "perl " . perforceWhere("//depot/swg/current/tools/InstallBootleg.pl") . " --list --force_newest --client_only --no_database $branch |") or reloop "Error running InstallBootleg.pl\n";
my $complete = 0;
while(<INSTALL>)
{
print;
$bootlegnum = $1 if(/^Updating to build: (\d+)/);
$complete = 1 if(/^Update complete/);
}
close(INSTALL);
print "Bootleg installation incomplete\n" if(!$complete);
print "Completed installing bootleg.\n" if($complete);
return $complete;
}
sub error
{
my $message = shift @_;
print SOCKET UNSUCCESSFUL_TEST;
print STDERR "$message\n";
goto FAIL;
}
sub fatal
{
my $message = shift @_;
print SOCKET UNSUCCESSFUL_TEST;
close(SOCKET);
die "$message\n";
}
sub makeDir
{
my(@tok, $check);
@tok = split(/\\|\//, $_[0]);
$check = shift(@tok);
foreach (@tok)
{
$check .= "/$_";
if(!(-d $check))
{
mkdir $check;
}
}
}
sub recieveBootleg
{
my $buffer;
return 0 if (read(SOCKET, $buffer, 4) != 4);
my $length = unpack("N", $buffer);
return 0 if(read(SOCKET, $branch, $length) != $length);
return 0 if (read(SOCKET, $buffer, 4) != 4);
$bootlegnum = unpack("N", $buffer);
print STDERR "Recieving bootleg $branch/$bootlegnum...\n";
my $directory = "";
while(1)
{
return 0 if (read(SOCKET, $buffer, 1) != 1);
last if($buffer eq END_BOOTLEG_SEND);
if($buffer eq BOOTLEG_SEND_DIRECTORY)
{
return 0 if (read(SOCKET, $buffer, 4) != 4);
$length = unpack("N", $buffer);
return 0 if (read(SOCKET, $directory, $length) != $length);
makeDir("$candela/SWO/swg_bootleg_builds/$branch/$bootlegnum/$directory");
chdir("$candela/SWO/swg_bootleg_builds/$branch/$bootlegnum/$directory") || reloop "Cannot chdir to $branch/$bootlegnum/$directory - $!\n";
}
if($buffer eq BOOTLEG_SEND_FILE)
{
return 0 if (read(SOCKET, $buffer, 2*4) != 2*4);
my ($fileNameLength, $fileSize) = unpack("NN", $buffer);
my $localFileName;
return 0 if (read(SOCKET, $localFileName, $fileNameLength) != $fileNameLength);
print STDERR "Receiving $branch/$bootlegnum/$directory/$localFileName ($fileSize bytes)\n";
open(F, ">$localFileName") || reloop ("could not open $localFileName for writing");
chmod (0755, $localFileName);
binmode(F);
while ($fileSize)
{
my $readSize = 16 * 1024;
$readSize = $fileSize if ($fileSize < $readSize);
my $readResult = read(SOCKET, $buffer, $readSize);
reloop "socket to controller machine abruptly terminated ($fileSize bytes remained)\n" if (!defined($readResult));
reloop "read incorrect amount ($fileSize bytes remained)\n" if ($readResult == 0);
print F $buffer;
$fileSize -= $readResult;
}
endbootleginstall("copied wrong number of bytes") if ($fileSize != 0);
close(F);
}
}
chdir("$candela/SWO/swg_bootleg_builds") || reloop "Cannot chdir to $candela - $!\n";;
print STDERR "Completed recieving bootleg $branch/$bootlegnum...\n";
}
sub testBootleg
{
my $buffer;
print STDERR "Initializing communication...\n";
error("problem reading from socket") if (read(SOCKET, $buffer, 4) != 4);
my $length = unpack("N", $buffer);
error("problem reading from socket") if(read(SOCKET, $branch, $length) != $length);
print STDERR "Testing bootleg for branch: $branch\n";
my $bootlegdir = perforceWhere("//depot/swg/$branch/bootleg/win32/...");
$bootlegdir =~ s/\.{3}//;
chdir($bootlegdir) or reloop "Cannot change to bootleg directory\n";
installBootleg() || fatal "Error installing bootleg";
print SOCKET pack("N", $bootlegnum);
error("problem reading from socket") if (read(SOCKET, $buffer, 1) != 1);
error("mismatch in client / server bootlegs")if($buffer eq BOOTLEG_MISMATCH);
error("server not ready") if ($buffer ne SERVER_READY);
print STDERR "Bootleg $bootlegnum verified with server - running client...\n";
my $killresult;
my $swgpid = open(SWGCLIENT, "SwgClient_o.exe -- -s ClientGame loginServerAddress=$build_cluster skipIntro=true skipSplash=true autoConnectToLoginServer=true loginClientID=bootleg loginClientPassword=bootleg avatarName=\"bootleg bootleg\" autoConnectToGameServer=true autoQuitAfterLoadScreen=true -s SharedFoundation demoMode=true |");
error("problem reading from socket") if (read(SOCKET, $buffer, 1) != 1);
if($buffer eq CLIENT_KILL)
{
kill 1, $swgpid;
error("Test unsuccessful - forced to kill client");
}
elsif($buffer eq CLIENT_OK)
{
# make sure we give the client a chance to exit on its own, then attempt to kill
print "Waiting for $waittime seconds for the client to end on its own...\n";
sleep($waittime);
$killresult = kill 1, $swgpid;
}
close(SWGCLIENT);
# clientResult = 1 if return value of SwgClient == 0 and we did not have to kill it ($killresult = 0)
my $clientResult = (!($? >> 8) && !$killresult);
print "clientresult=$clientResult killresult=$killresult exitresult=$?\n";
print SOCKET ($clientResult == 1) ? SUCCESSFUL_TEST : UNSUCCESSFUL_TEST;
if($clientResult == 1)
{
open(BLESS, ">$candela/SWO/swg_bootleg_builds/$branch/$bootlegnum/blessed.txt");
close(BLESS);
}
print STDERR "Test was " . (($clientResult == 1) ? "successful\n" : "unsuccessful\n") . "\n";
}
sub upkeep
{
my $buffer;
return 0 if (read(SOCKET, $buffer, 4) != 4);
my $length = unpack("N", $buffer);
return 0 if(read(SOCKET, $branch, $length) != $length);
print STDERR "Performing upkeep on bootleg directory for $branch...\n";
my @bootlegs;
my $removedbootlegs = 0;
my $buildcluster;
print STDERR "Getting bootleg version on build cluster...\n";
my $controller = perforceWhere("//depot/swg/current/tools/build_cluster_controller.pl");
open(BUILD, "perl $controller -bootleg-version 2>&1 |");
while(<BUILD>)
{
$buildcluster = $1 if(/^Build cluster bootleg version is: (\d+)/);
}
close(BUILD);
if(!defined $buildcluster)
{
print STDERR "Could not get build cluster bootleg version.\n";
print SOCKET FAILED_GETTING_BUILD_CLUSTER_VERSION;
return 0;
}
else
{
print STDERR "Build cluster bootleg version is $buildcluster.\n";
print SOCKET GOT_BUILD_CLUSTER_VERSION;
print SOCKET pack("N", $buildcluster);
}
opendir DH, "$candela/SWO/swg_bootleg_builds/$branch" or fatal "Cannot open $candela/SWO/swg_bootleg_builds/$branch: $!\n";
foreach (readdir DH)
{
push @bootlegs, $_ if(/^\d+$/ && -d ("$candela/SWO/swg_bootleg_builds/$branch/$_"));
}
closedir DH;
@bootlegs = sort { $a <=> $b } @bootlegs;
while(@bootlegs > $numbootlegs)
{
my $bootleg = shift @bootlegs;
next if($buildcluster == $bootleg);
print STDERR "Removing bootleg $bootleg...\n";
system("rm -fr $candela/SWO/swg_bootleg_builds/$branch/$bootleg");
print SOCKET pack("N", $bootleg);
++$removedbootlegs;
}
print SOCKET pack("N", 0);
print STDERR "Completed upkeep on bootleg directory - removed $removedbootlegs bootlegs.\n";
my $removedpdbs = 0;
print STDERR "Performing upkeep on pdb directory...\n";
opendir DH, "$candela/SWO/pdbs" or fatal "Cannot open $candela/SWO/pdbs: $!\n";
foreach (sort readdir DH)
{
my $pdbfile = $_;
if($pdbfile =~ /^\d+_0_$branch\.zip$/ && -M "$candela/SWO/pdbs/$pdbfile" > $pdbtime)
{
print STDERR "Deleting $pdbfile...\n";
#system("rm -f $candela/SWO/pdbs/$pdbfile");
print SOCKET pack("N", length $pdbfile);
print SOCKET $pdbfile;
++$removedpdbs;
}
}
closedir DH;
print SOCKET pack("N", 0);
print STDERR "Completed upkeep on pdb directory - removed $removedpdbs pdbs.\n\n";
return 1;
}
sub endEmail
{
print SOCKET pack("N", 0);
return 0;
}
sub bootlegDirDescending
{
my($a, $b) = @_;
# Both are numbers
return $b <=> $a if($a =~ /^\d+$/ && $b =~ /^\d+$/);
# Both are not numbers
return $a cmp $b if(!($a =~ /^\d+$/) && !($b =~ /^\d+$/));
# $a is a number, $b is not
return -1 if($a =~ /^\d+$/);
# $a is not a number, $ b is
return 1;
}
sub email
{
my $currentBootleg = "";
my $oldBootleg = "";
my $buffer;
return endEmail() if(read(SOCKET, $buffer, 4) != 4);
my $currentBootlegLength = unpack("N", $buffer);
return endEmail() if($currentBootlegLength == 0);
return endEmail() if(read(SOCKET, $currentBootleg, $currentBootlegLength) != $currentBootlegLength);
opendir DH, "$candela/SWO/swg_bootleg_builds/$branch" or fatal "Cannot open $candela/SWO/swg_bootleg_builds/$branch: $!\n";
foreach (sort { bootlegDirDescending($b, $a) } readdir DH)
{
# we want the 1st blessed one that is not the one we are looking at
next if($currentBootleg eq $_);
if(/^\d+$/ && -d "$candela/SWO/swg_bootleg_builds/$branch/$_" && -f "$candela/SWO/swg_bootleg_builds/$branch/$_/blessed.txt")
{
$oldBootleg = $_;
last;
}
}
closedir DH;
print SOCKET pack("N", length $oldBootleg);
print SOCKET $oldBootleg;
print STDERR "Completed sending information to build_bootleg_linux.\n";
}
# ======================================================================
# Main
# ======================================================================
# open the daemon socket
print STDERR "Opening socket\n";
socket(LISTEN, PF_INET, SOCK_STREAM, getprotobyname('tcp')) || die "socket failed\n";
setsockopt(LISTEN, SOL_SOCKET, SO_REUSEADDR, 1) || die "setsockopt failed\n";
my $addr = sockaddr_in($port, INADDR_ANY);
bind(LISTEN, $addr) || die "bind failed\n";
listen(LISTEN, 1) || die "listen failed\n";
BUILDLOOP:
while (1)
{
print STDERR "Waiting on a connection...\n";
accept(SOCKET, LISTEN) || reloop "accept failed\n";
# make binary and unbuffer the socket
binmode(SOCKET);
my $oldSelect = select(SOCKET);
$| = 1;
select($oldSelect);
my $buffer;
error("problem reading from socket") if (read(SOCKET, $buffer, 1) != 1);
if($buffer eq START_BOOTLEG_TEST)
{
print "Got message to initiate bootleg test.\n";
testBootleg();
}
elsif($buffer eq START_UPKEEP)
{
print "Got message to perform upkeep.\n";
upkeep();
}
elsif($buffer eq START_BOOTLEG_SEND)
{
print "Got message to start recieving bootleg.\n";
recieveBootleg();
}
elsif($buffer eq START_EMAIL)
{
print "Got message to start email.\n";
email();
}
FAIL:
close(SOCKET);
}

744
tools/build_cluster_controller.pl Executable file
View File

@@ -0,0 +1,744 @@
#! /usr/bin/perl
# ======================================================================
# ======================================================================
use strict;
use warnings;
use Socket;
use File::Copy;
# ======================================================================
# Constants
# ======================================================================
use constant START_COMMUNICATION => "S";
use constant START_NOT_LOCKED_READY => "B";
use constant START_LOCKED_READY => "C";
use constant START_LOCKED_READY_UNAUTHORIZED_USER => "L";
use constant START_ERROR_AUTHORIZING => "K";
use constant END_COMMUNICATION => "E";
use constant END_SUCCESSFULL => "F";
use constant SUCCESSFULL_COMMAND => "P";
use constant FAILED_COMMAND => "U";
use constant UPDATE_BOOTLEG_STEP_OK => "G";
use constant UPDATE_BOOTLEG_STEP_FAILED => "H";
use constant UPDATE_BOOTLEG_SEND_DIRECTORY => "M";
use constant UPDATE_BOOTLEG_SEND_FILE => "N";
use constant UPDATE_BOOTLEG_FILES_FINISHED => "Q";
use constant SNAPSHOT_FAILED => "O";
use constant SNAPSHOT_SUCCESSFULL => "P";
use constant COMMAND_RESTART => "a";
use constant COMMAND_RESTART_LOGIN => "b";
use constant COMMAND_RESTART_NODES => "c";
use constant COMMAND_LOCK => "d";
use constant COMMAND_UNLOCK => "e";
use constant COMMAND_UPDATE_BOOTLEG => "f";
use constant COMMAND_CONTENT_SYNC => "g";
use constant COMMAND_SYNC_SPECIFIED_CHANGELISTS => "h";
use constant COMMAND_SNAPSHOT => "i";
use constant COMMAND_BOOTLEG_VERSION => "j";
use constant COMMAND_FREE_OBJECT_IDS => "k";
# ======================================================================
# Globals
# ======================================================================
my $buildCluster = "swo-dev9.station.sony.com";
my $port = "98452";
my $candela = "p:";
my $exitcode = 0;
my $name = $0;
$name =~ s/^(.*)\\//;
my $option;
my $command;
my $user;
# ======================================================================
# Subroutines
# ======================================================================
sub usage
{
print STDERR "\nUsage:\n";
print STDERR "\t$name [command(s)]\n\n".
"\t\t-restart :\n\t\t\t restart the build cluster (central node)\n".
"\t\t-restart-login :\n\t\t\t restart the Login server\n".
"\t\t-restart-nodes :\n\t\t\t restart all nodes of the build cluster\n".
"\t\t-lock :\n\t\t\t lock the build cluster (must be authorized user)\n".
"\t\t-unlock :\n\t\t\t unlock the build cluster (must be authorized user)\n".
"\t\t-update-bootleg <branch> :\n\t\t\t update the bootleg on the build cluster (p4 key check) - needs to be run in windows\n".
"\t\t-bootleg-version:\n\t\t\t check bootleg version on the build cluster\n".
"\t\t-free-object-ids :\n\t\t\t free object IDs in the database for the build cluster\n".
"\t\t-content-sync [changelist] :\n\t\t\t shut down, content sync to specific changelist (if none, content sync to head), bring up\n".
"\t\t-sync-specified-changelists <changelist [| changelist]> :\n\t\t\t shut down, sync to multiple specified changelists, bring up\n".
"\t\t-snap <schema> <branch> [dontsubmit] :\n\t\t\t free object IDs, make a snapshot, verifies before adding files to <branch> in perforce\n\t\t\t and submits unless [dontsubmit]\n".
"\t\t\t If <schema> does not exist, it is created otherwise it is overwritten\n".
"\n\tIf multiple commands are given, the build cluster will go down / come up only once around the commands (if necessary)\n";
die "\n";
}
sub exitFailed
{
$exitcode = 1;
goto FAIL;
}
sub perforceWhere
{
local $_;
# find out where a perforce file resides on the local machine
my $result;
{
open(P4, "p4 where $_[0] |");
$_ = <P4>;
chomp;
my @where = split;
$result = $where[2];
close(P4);
}
return $result;
}
sub checkarguments()
{
my @args = @ARGV;
while(@args)
{
my $elem = shift @args;
# check if the key is valid if the command requires one
if($elem =~ /^-snap$/)
{
$elem = shift @args;
&usage() if(!(defined $elem) || $elem =~ /^-/);
$elem = shift @args;
&usage() if(!(defined $elem) || $elem =~ /^-/);
# check for optional parameter
shift @args if((defined $args[0]) && $args[0] eq "dontsubmit");
}
elsif($elem =~ /^-update-bootleg$/)
{
$elem = shift @args;
&usage() if(!(defined $elem) || $elem =~ /^-/);
}
elsif($elem =~ /^-content-sync$/)
{
shift @args if(@args && !($args[0] =~ /^-/));
}
elsif($elem =~ /^-sync-specified-changelists$/)
{
$elem = shift @args;
&usage() if(!defined $elem || $elem =~ /^-/);
while(@args)
{
last if($args[0] =~ /^-/);
shift @args;
}
}
elsif(!($elem =~ /^-restart$/ || $elem =~ /^-restart-login$/ || $elem =~ /^-restart-nodes$/ || $elem =~ /^-lock$/ || $elem =~ /^-unlock$/ || $elem =~ /^-bootleg-version$/ || $elem =~ /^-free-object-ids$/ || $elem =~ /^-build_script_publish$/))
{
&usage();
}
}
}
sub openbuildsocket
{
socket(BUILD, PF_INET, SOCK_STREAM, getprotobyname('tcp')) || die "socket failed\n";
{
my $destination = inet_aton($buildCluster) || die "inet_aton failed\n";
my $paddr = sockaddr_in($port, $destination);
connect(BUILD, $paddr) || die "connect failed\n";
# unbuffer the socket
my $oldSelect = select(BUILD);
$| = 1;
select($oldSelect);
# put the socket into binary mode
binmode BUILD;
}
}
sub getuser
{
my $user;
open(P4, "p4 user -o |") || die "p4 user failed\n";
while(<P4>)
{
$user = $1 if(/^User:\s+(\S+)/);
}
close(P4);
die "Could not get perforce user\n" if(!defined $user);
return $user;
}
sub sendstartinfo
{
print STDERR "Contacting build cluster...\n";
print BUILD START_COMMUNICATION;
my $initializer = $user;
$initializer = "buildscript" if($user eq "build_script_publish");
my $length = length $initializer;
print BUILD pack("N", $length);
print BUILD $initializer;
my $returncode;
if(read(BUILD, $returncode, 1) != 1)
{
print STDERR "Problem contacting build server\n";
return 0;
}
if($returncode eq START_NOT_LOCKED_READY)
{
print STDERR "Build server is not locked and ready\n\n";
return 1;
}
elsif($returncode eq START_LOCKED_READY)
{
print STDERR "Build server is locked and ready\n\n";
return 1;
}
elsif($returncode eq START_LOCKED_READY_UNAUTHORIZED_USER)
{
print STDERR "Build server is locked (limited access for non-authoritative user)\n\n";
return 1;
}
elsif($returncode eq START_ERROR_AUTHORIZING)
{
print STDERR "problem authorizing $user for build server\n\n";
return 0;
}
else
{
print STDERR "Build server not ready\n\n";
return 0;
}
}
sub sendendinfo
{
print STDERR "Ending communication with build cluster...\n";
print BUILD END_COMMUNICATION;
my $returncode;
my $readreturn = read(BUILD, $returncode, 1);
if(!defined $readreturn || $readreturn != 1)
{
print STDERR "Build server communication ended abruptly\n";
return 0;
}
if($returncode eq END_SUCCESSFULL)
{
print STDERR "Build server communication ended successfully\n";
return 1;
}
else
{
print STDERR "Build server communication ended with errors\n";
return 0;
}
}
sub contentsync
{
my $changelist = "";
$changelist = shift @ARGV if(@ARGV && !($ARGV[0] =~ /^-/));
my $length = length $changelist;
print BUILD pack("N", $length);
print BUILD $changelist;
# Recieve any errors from the content sync
my $buffer;
return 0 if(read(BUILD, $buffer, 4) != 4);
$length = unpack("N", $buffer);
return 0 if(read(BUILD, $buffer, $length) != $length);
print $buffer;
return 1;
}
sub syncspecifiedchangelists
{
my $changelists = "";
while(@ARGV)
{
last if($ARGV[0] =~ /^-/);
my $elem = shift @ARGV;
$changelists .= "$elem ";
}
chomp $changelists;
if($changelists eq "")
{
print BUILD pack("N", 0);
print STDERR "You must specify changelist\(s\)\n";
return 0;
}
my $length = length $changelists;
print BUILD pack("N", $length);
print BUILD $changelists;
return 1;
}
sub endsubmit
{
print "Error running: $_[0]\n";
return 0;
}
sub submitopenfiles
{
my $dontsubmit = shift;
local $_;
my @files;
system("p4 revert -a > /dev/null");
open(P4, "p4 -ztag opened -c default |");
while (<P4>)
{
chomp;
push (@files, $_) if (s/^\.\.\. depotFile //);
}
close(P4);
if(!@files)
{
print STDERR "No changed files, nothing to submit\n";
return 1;
}
my $tmpfile = "submit.tmp";
# submit all the open files
open(TMP, ">" . $tmpfile);
print TMP "Change:\tnew\n";
print TMP "\nDescription:\n";
foreach (@_)
{
print TMP "\t", $_, "\n";
}
print TMP "\nFiles:\n";
foreach (@files)
{
print TMP "\t", $_, "\n";
}
close(TMP);
if ($dontsubmit)
{
open(P4, "p4 change -i < $tmpfile |") || return 0;
while(<P4>)
{
print STDERR "Successfully created changelist $1\n" if(/Change (\d+) created/);
}
close(P4);
}
else
{
open(P4, "p4 submit -i < $tmpfile |") || return 0;
while(<P4>)
{
print STDERR "Successfully submitted at changelist $1\n" if(/Change (\d+) submitted/);
}
close(P4);
}
return 0 if ($? != 0);
unlink($tmpfile);
return 1;
}
sub snapshot
{
my $dbSchema = shift @ARGV;
my $branch = shift @ARGV;
my $dontsubmit = 0;
my $snapshotLog = "";
my $buffer = "";
my $p4operation = "submit";
if (defined($ARGV[0]) && $ARGV[0] eq "dontsubmit")
{
$dontsubmit = 1;
$p4operation = "change";
shift @ARGV;
}
print BUILD pack("N", length $dbSchema);
print BUILD $dbSchema;
if(read(BUILD, $buffer, 1) != 1 || $buffer eq SNAPSHOT_FAILED)
{
print STDERR "Snapshot not created successfully on the build cluster\n";
return 0;
}
# Recieve files
my @worldSnapshots;
print STDERR "Snapshot generation complete.\n";
while(1)
{
return 0 if (read(BUILD, $buffer, 2*4) != 2*4);
my ($fileSize, $fileNameLength) = unpack("NN", $buffer);
# check if we are finished
last if($fileSize == 0 && $fileNameLength == 0);
my $localFileName;
return 0 if (read(BUILD, $localFileName, $fileNameLength) != $fileNameLength);
# first file sent will be the snapshot log
$snapshotLog = $localFileName if($snapshotLog eq "");
# add all ws files to the array
push @worldSnapshots, $localFileName if($localFileName =~ /\.ws$/);
# receive the binary bits for the file
print STDERR "Receiving $localFileName ($fileSize bytes)...";
unlink $localFileName;
open(F, ">" . $localFileName) || return endbootleginstall("could not open $localFileName for writing");
binmode(F);
while ($fileSize)
{
my $readSize = 16 * 1024;
$readSize = $fileSize if ($fileSize < $readSize);
my $readResult = read(BUILD, $buffer, $readSize);
return 0 if (!defined($readResult));
return 0 if ($readResult == 0);
print F $buffer;
$fileSize -= $readResult;
}
return 0 if ($fileSize != 0);
close(F);
print "done\n";
}
# Echo log to user
print STDERR "--- Start of snapshot log:\n";
system("cat $snapshotLog") == 0 || return 0;
print STDERR "--- End of snapshot log:\n";
# Only verify using STDIN if we are not being called by the build script
if($user ne "build_script_publish")
{
print STDERR "\nAre the world snapshots ok to do perforce $p4operation? (y/n)\n";
while(<STDIN>)
{
chomp;
if($_ eq "y" || $_ eq "Y")
{
last;
}
elsif($_ eq "n" || $_ eq "N")
{
return 1;
}
print STDERR "Please enter \'y\' or \'n\'\n";
}
}
# If we get here, we have decided to submit
print STDERR "Proceeding with $p4operation\n";
# Get a hash of the current world snapshots in perforce
my %ws;
open(FILES, "p4 files //depot/swg/$branch/data/sku.0/sys.client/built/game/snapshot/... |") || return endsubmit("p4 files");
while(<FILES>)
{
$ws{$1} = 1 if(/\/([^\/]+\.ws)#/);
}
close(FILES);
# Edit files and move to appropriate directory
system("p4 edit //depot/swg/$branch/data/sku.0/sys.client/built/game/snapshot/...") == 0 || return endsubmit("p4 edit snapshot dir");
foreach(@worldSnapshots)
{
system("p4 add //depot/swg/$branch/data/sku.0/sys.client/built/game/snapshot/$_") == 0 || return endsubmit("p4 add") if(!exists($ws{$_}));
copy($_, perforceWhere("//depot/swg/$branch/data/sku.0/sys.client/built/game/snapshot/$_")) || return endsubmit("moving *.ws to snapshot dir");
}
system("p4 edit //depot/swg/$branch/dsrc/sku.0/sys.client/built/game/snapshot/swg_object.txt") == 0 || return endsubmit("p4 edit swg_object.txt");
copy("swg_object.txt", perforceWhere("//depot/swg/$branch/dsrc/sku.0/sys.client/built/game/snapshot/swg_object.txt")) || return endsubmit("moving object file to swg_object.txt");
# create golddata text file
createGoldDataFile($dbSchema, $branch);
submitopenfiles($dontsubmit, "[automated]", "New snapshots for $branch from build_cluster_controller ($dbSchema)") || return endsubmit("p4 $p4operation");
return 1;
}
sub createGoldDataFile
{
my ($dbSchema, $branch) = @_;
my $goldDataFile = perforceWhere("//depot/swg/$branch/src/game/server/database/build/linux/golddata.txt");
system("p4 edit $goldDataFile");
open(GOLDDATA, "> $goldDataFile");
print GOLDDATA "$dbSchema\n";
close GOLDDATA;
system("p4 add $goldDataFile");
}
sub getbootlegversion
{
my $buffer;
return 0 if(read(BUILD, $buffer, 4) != 4);
my $length = unpack("N", $buffer);
return 0 if(read(BUILD, $buffer, $length) != $length);
if($length == 0)
{
print STDERR "Could not get build cluster bootleg version\n";
return 0;
}
print STDERR "Build cluster bootleg version is: $buffer\n";
return 1;
}
sub updatebootleg
{
my $branch = shift @ARGV;
# Get the number of the most recent bootleg
my $dir = "$candela/swo/builds/$branch";
my $buffer;
my $change = 0;
opendir DH, $dir or return 0;
foreach (readdir DH)
{
$change = $_ if(/^\d+$/ && -d ($dir."/".$_) && $_ > $change);
}
closedir DH;
return 0 if(!$change);
print STDERR "Most recent blessed bootleg is: $change\n";
# Send info to build cluster
print STDERR "Syncing build cluster to $change...\n";
print BUILD pack("N", $change);
return 0 if(read(BUILD, $buffer, 1) != 1 || $buffer ne UPDATE_BOOTLEG_STEP_OK);
print STDERR "Sync of build cluster complete.\n";
# Compress the server binaries
my $file = "servers_debug.tar.gz";
print STDERR "Compressing server binaries...\n";
system("tar --create --gzip --directory=$dir/$change/servers_debug --file=/tmp/$file .") == 0 || die "Failed to compress $dir/$change/servers_debug";
print STDERR "Compress server binaries complete.\n";
# Send file to build cluster
die "Can't find server zip file!\n" if (!-s "c:/cygwin/tmp/$file");
my $fileSize = -s "c:/cygwin/tmp/$file";
print STDERR "Sending file $file ($fileSize bytes)\n";
print BUILD pack("NN", $fileSize, length $file);
print BUILD $file;
open(F, "<c:/cygwin/tmp/$file");
binmode(F);
while ($fileSize)
{
my $buffer;
my $readSize = 16 * 1024;
$readSize = $fileSize if ($fileSize < $readSize);
my $readResult = read(F, $buffer, $readSize);
die "unexpected end of file" if (!defined($readResult));
die "did not read what we expected to" if ($readResult != $readSize);
print BUILD $buffer;
$fileSize -= $readResult;
}
die "copied all the bytes but not at EOF" if (!eof(F));
close(F);
# Cleanup
unlink "c:/cygwin/tmp/$file";
if(read(BUILD, $buffer, 1) != 1 || $buffer ne UPDATE_BOOTLEG_STEP_OK)
{
print "Failed while sending file.\n";
closedir DH;
return 0;
}
print "$file sent.\n";
print STDERR "Updating database on build cluster...\n";
return 0 if(read(BUILD, $buffer, 1) != 1 || $buffer ne UPDATE_BOOTLEG_STEP_OK);
print STDERR "Database update on build cluster complete.\n";
print STDERR "Syncing individual changelists on build cluster...\n";
my @syncChangelists;
open(SYNC, "$candela/SWO/builds/$branch/$change/sync.txt") || return 0;
while(<SYNC>)
{
chomp;
push @syncChangelists, $_;
}
close(SYNC);
print BUILD pack("N", length (join(" ", @syncChangelists)));
print BUILD join(" ", @syncChangelists);
return 0 if(read(BUILD, $buffer, 1) != 1 || $buffer ne UPDATE_BOOTLEG_STEP_OK);
print STDERR "Inidividual changelist sync complete.\n";
return 1;
}
# ======================================================================
# Main
# ======================================================================
&usage if(@ARGV == 0);
# Check to see if we're testing
if($ARGV[0] eq "vthakkar-box")
{
shift;
$buildCluster = "lin-vthakkar.station.sony.com";
}
$user = getuser();
$user = "build_script_publish" if(grep("-build_script_publish" eq $_, @ARGV));
checkarguments();
openbuildsocket();
sendstartinfo() || exitFailed();
while(@ARGV)
{
$option = shift @ARGV;
if($option eq "-restart")
{
print STDERR "Restarting build cluster...\n";
print BUILD COMMAND_RESTART;
}
elsif($option eq "-restart-login")
{
print STDERR "Restarting loginserver on build cluster...\n";
print BUILD COMMAND_RESTART_LOGIN;
}
elsif($option eq "-restart-nodes")
{
print STDERR "Restarting build cluster nodes...\n";
print BUILD COMMAND_RESTART_NODES;
}
elsif($option eq "-lock")
{
print STDERR "Locking build cluster...\n";
print BUILD COMMAND_LOCK;
}
elsif($option eq "-unlock")
{
print STDERR "Unlocking build cluster...\n";
print BUILD COMMAND_UNLOCK;
}
elsif($option eq "-update-bootleg")
{
print STDERR "Updating bootleg on build cluster...\n";
print BUILD COMMAND_UPDATE_BOOTLEG;
updatebootleg() || goto ERROR;
}
elsif($option eq "-content-sync")
{
print STDERR "Content syncing build cluster...\n";
print BUILD COMMAND_CONTENT_SYNC;
contentsync() || goto ERROR;
}
elsif($option eq "-sync-specified-changelists")
{
print STDERR "Syncing build cluster to changelists...\n";
print BUILD COMMAND_SYNC_SPECIFIED_CHANGELISTS;
syncspecifiedchangelists() || goto ERROR;
}
elsif($option eq "-snap")
{
print STDERR "Creating snapshot on build cluster...\n";
print BUILD COMMAND_SNAPSHOT;
snapshot() || goto ERROR;
}
elsif($option eq "-bootleg-version")
{
print STDERR "Checking bootleg version on build cluster...\n";
print BUILD COMMAND_BOOTLEG_VERSION;
getbootlegversion() || goto ERROR;
}
elsif($option eq "-free-object-ids")
{
print STDERR "Freeing object ids on build cluster...\n";
print BUILD COMMAND_FREE_OBJECT_IDS;
}
elsif($option eq "-build_script_publish")
{
next;
}
else
{
print STDERR "Error: cannot decipher option: $option\n";
goto FAIL;
}
ERROR:
my $success;
exitFailed() if(!read(BUILD, $success, 1));
if($success eq SUCCESSFULL_COMMAND)
{
print STDERR "Successfully completed $option\n\n";
}
else
{
print STDERR "Error encountered while running $option\n\n";
exitFailed();
}
}
FAIL:
sendendinfo();
close(BUILD);
exit($exitcode);

1160
tools/build_cluster_daemon.pl Executable file

File diff suppressed because it is too large Load Diff

19
tools/buildtre.btm Normal file
View File

@@ -0,0 +1,19 @@
@echo off
if not exist "common.cfg" goto error_win32
if "%1" == "" goto error_usage
if "%2" == "" goto error_usage
perl ..\..\tools\buildPatchTreeRsp.pl common.cfg patch_%1_%2.rsp %1..%2
..\..\tools\TreeFileBuilder -r patch_%1_%2.rsp patch_%1_%2.tre
copy patch_%1_%2.tre p:\swo\swg_bootleg_builds\tre
echo searchTreeX=patch_%1_%2.tre >> p:\swo\swg_bootleg_builds\tre\common_tre.cfg
goto end
:error_win32
echo You must run this from the exe\win32 directory!
goto end
:error_usage
echo usage: BuildTre changelist1 changelist2
:end

28
tools/checkChunkLoading.pl Executable file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/perl
# Given a planet name, searches a log file to check that every chunk on that planet was loaded
($targetPlanet, $logfile)=@ARGV;
open(LOGFILE,$logfile);
while (<LOGFILE>)
{
if (/ChunkLocator:Chunk (\w+) ([-\d]+) ([-\d]+)/)
{
($planet, $x, $z) = ($1, $2, $3);
if ($planet eq $targetPlanet)
{
$chunks{$x.":".$z}+=1;
}
}
}
for ($x=-8000; $x<=8000; $x+=100)
{
for ($z=-8000; $z<=8000; $z+=100)
{
if ($chunks{$x.":".$z}!=2)
{
print "Chunk error $targetPlanet $x,$z. Was in logs ".($chunks{$x.":".$z}+0)." times (should be 2 times)\n";
}
}
}

54
tools/checkCreatureStrings.pl Executable file
View File

@@ -0,0 +1,54 @@
# ================================================================================
#
# checkCreatureStrings.pl
# Copyright 2006, Sony Online Entertainment LLC
#
# ================================================================================
use Cwd;
# --------------------------------------------------------------------------------
die "usage: $0\n\t Checks that all creatures.tab creature names are localized. Outputs missing creature names." if (@ARGV);
die "Must be run within a swg directory!" if (getcwd() !~ m!(.*/swg/\w+/)!);
my $rootPath = $1;
my $creaturesStringFile = "data/sku.0/sys.shared/built/game/string/en/mob/creature_names.stf";
my $creaturesTabFile = "dsrc/sku.0/sys.server/compiled/game/datatables/mob/creatures.tab";
my $localizationToolCon = "../all/tools/all/win32/LocalizationToolCon_r.exe";
# --------------------------------------------------------------------------------
open(CS, "$rootPath$localizationToolCon $rootPath$creaturesStringFile -list |") || die "$!";
while (<CS>)
{
split;
$creaturesString{$_[0]} = 1;
}
close(CS);
open(CT, "$rootPath$creaturesTabFile") || die "$!";
<CT>; <CT>; # skip column header name & type
while (<CT>)
{
split;
if (!$creaturesString{$_[0]})
{
print "$_[0]\n";
++$missingStringCount;
}
}
close(CT);
if ($missingStringCount)
{
print STDERR "\nFAILURE! Missing $missingStringCount creature name strings!\n";
}
else
{
print STERR "\nSUCCESS! No missing creature strings!\n";
}
exit $missingStringCount;
# ================================================================================

70
tools/checkWritableSrc.pl Executable file
View File

@@ -0,0 +1,70 @@
#!/usr/bin/perl -w
use File::Find;
use BuildFunctions;
##
# This subroutine finds any non-authorized writable files in a passed directory
sub Find_Writable
{
if (-d $_)
{
# found a directory entry
# prune the directory if it's one we want to ignore
if (m/^(compile)$/)
{
#prune it
$File::Find::prune = 1;
}
}
elsif (-f and -w $_)
{ if (!m/^.*(aps|ncb|opt|plg)$/)
{
print "n $File::Find::name\n";
print Logfile "n $File::Find::name\n";
}
}
} # End of sub Find_Writable
########## MAIN ##########
# Email addresses
$gmcdaniel = "gmcdaniel\@soe.sony.com";
##
# Check for any non-authorized writable files in the /swg/current/src directory and email the results
$writable_files_log = "WritableFiles.log";
print ("Checking for writable files...\n");
open (Logfile, ">c:\\buildlogs\\$writable_files_log") || die "Sorry, I couldn't create $writable_files_log";
print Logfile "The writable files that were found:\n";
# do a find
$search_path = "..\\src";
@ARGV = ($search_path);
find(\&Find_Writable, @ARGV);
close (Logfile);
$writable_test_time_and_date = get_time_and_date();
$date_stamp = get_date();
system ("copy c:\\buildlogs\\$writable_files_log c:\\buildlogs\\WritableFiles_$writable_test_time_and_date.log");
print ("Checking for writable files completed\n");
print ("\n");
print ("\n");
system ("postie -host:mail-sd.station.sony.com -to:$gmcdaniel -from:$gmcdaniel -s:\"Writable Files Results $date_stamp\" -nomsg -file:c:\\buildlogs\\WritableFiles_$writable_test_time_and_date.log");
#
## End of Check for any non-authorized writable files in the /swg/current/src directory and email the results
########## END OF MAIN ##########

84
tools/check_environment.pl Executable file
View File

@@ -0,0 +1,84 @@
#!/usr/bin/perl
# Script to test the environment for a server
# Looks at enviroment variables, etc., to make
# sure everything is installed
&checkJava;
&checkOracle;
&summary;
sub checkJava
{
$ldpath=$ENV{"LD_LIBRARY_PATH"};
if (!($ldpath =~ /java/))
{
&error("Java must be in LD_LIBRARY_PATH.\n");
}
}
# Check the oracle installation
# Note: May need to change the name of the database to
# match whatever the production database gets called.
sub checkOracle
{
$ldpath=$ENV{"LD_LIBRARY_PATH"};
if (!($ldpath =~ /oracle/))
{
&error("\$ORACLE_HOME/lib must be in LD_LIBRARY_PATH.\n");
}
$oracleHome=$ENV{"ORACLE_HOME"};
if ($oracleHome eq "")
{
&error("ORACLE_HOME is not set. Remaining Oracle tests skipped.\n");
}
else
{
open (TESTCASE,"sqlplus buildcluster/changeme\@swodb < oracletest.sql 2>&1|");
while (<TESTCASE>)
{
# print;
if (/ERROR/)
{
$_=<TESTCASE>;
if (/12154/) # could not resolve service name
{
&error ("swodb service is not set up in \$ORACLE_HOME/network/admin/tnsnames.ora\n");
}
elsif (/01017/)
{
&error ("Invalid username or password for Oracle. Check that the swodb service in \$ORACLE_HOME/network/admin/tnsnames.ora is pointing to the correct database server.\n");
}
else
{
&error ("Oracle error: $_\n");
}
}
if (/command not found/)
{
&error ("\$ORACLE_HOME/bin is not in the path.\n");
}
}
}
}
# Display an error message and count the number of errors
sub error
{
my ($message) = @_;
print STDERR $message;
++$errorCount;
}
sub summary
{
if ($errorCount == 0)
{
print "No problems detected.\n";
}
else
{
die "$errorCount problem(s) detected.\n";
}
}

View File

@@ -0,0 +1,183 @@
# ======================================================================
# collectAssetCustomizationInfo.pl
# Copyright 2003, Sony Online Entertainment, Inc.
# All rights reserved.
# ======================================================================
use strict;
use AppearanceTemplate;
use BlueprintTextureRendererTemplate;
use ComponentAppearanceTemplate;
use CustomizableShaderTemplate;
use CustomizationVariableCollector;
use DetailAppearanceTemplate;
use LightsaberAppearanceTemplate;
use LodMeshGeneratorTemplate;
use MeshAppearanceTemplate;
use PortalAppearanceTemplate;
use SkeletalAppearanceTemplate;
use SkeletalMeshGeneratorTemplate;
use SwitchShaderTemplate;
use TreeFile;
use VehicleCustomizationVariableGenerator;
# ======================================================================
my $branch = "current";
my $debug = 0;
my $treeFileLookupDataFile;
# ======================================================================
sub printUsage
{
print "Usage:\n";
print "\tperl collectAssetCustomizationInfo.pl [-d] [-h] [-b <branch>] -t <treefile lookup filename>\n";
print "\n";
print "-d: if specified, turns on debugging info (Default: off)\n";
print "-h: print this help\n";
print "-t: loads the TreeFile lookup data from the specified filename\n";
}
# ----------------------------------------------------------------------
sub processCommandLineArgs
{
my $printHelp = 0;
my $requestedHelp = 0;
# Grab options from commandline.
while ((scalar @_) && !$printHelp)
{
if ($_[0] =~ m/^-h/)
{
$printHelp = 1;
$requestedHelp = 1;
}
elsif ($_[0] =~ m/^-b/)
{
shift;
$branch = $_[0];
if (!defined($branch))
{
print "User must specify a branch name after the -t option, printing help.\n";
$printHelp = 1;
}
else
{
print "\$branch=[$branch]\n" if $debug;
}
}
elsif ($_[0] =~ m/^-d/)
{
$debug = 1;
}
elsif ($_[0] =~ m/^-t/)
{
shift;
$treeFileLookupDataFile = $_[0];
if (!defined($treeFileLookupDataFile))
{
print "User must specify a treefile lookup data filename after the -t option, printing help.\n";
$printHelp = 1;
}
else
{
print "\$treeFileLookupDataFile=[$treeFileLookupDataFile]\n" if $debug;
}
}
else
{
print "Unsupported option [$_[0]], printing help.\n";
$printHelp = 1;
}
# Shift past current argument.
shift;
}
# Check if we're missing anything required.
if (!$requestedHelp)
{
if (!defined($treeFileLookupDataFile))
{
print "No TreeFile lookup data file specified, printing usage info.\n";
$printHelp = 1;
}
}
if ($printHelp)
{
printUsage();
exit ($requestedHelp ? 0 : -1);
}
}
# ----------------------------------------------------------------------
sub initialize
{
# Initialize data handlers.
&AppearanceTemplate::install();
&BlueprintTextureRendererTemplate::install();
&ComponentAppearanceTemplate::install();
&CustomizableShaderTemplate::install();
&DetailAppearanceTemplate::install();
&LightsaberAppearanceTemplate::install();
&LodMeshGeneratorTemplate::install();
&MeshAppearanceTemplate::install();
&PortalAppearanceTemplate::install();
&SkeletalAppearanceTemplate::install();
&SkeletalMeshGeneratorTemplate::install();
&SwitchShaderTemplate::install();
&VehicleCustomizationVariableGenerator::install();
# Open the TreeFile lookup datafile.
my $dataFileHandle;
die "Failed to open [$treeFileLookupDataFile]: $!" unless open($dataFileHandle, "< " . $treeFileLookupDataFile);
# Initialize the treefile.
TreeFile::loadFileLookupTable($dataFileHandle);
# Close the TreeFile lookup datafile.
die "Failed to close [$treeFileLookupDataFile]: $!" unless close($dataFileHandle);
}
# ======================================================================
# Main Program
# ======================================================================
# Handle command line.
processCommandLineArgs(@ARGV);
# Initialize subsystems (e.g. TreeFile)
initialize();
# Setup the list of patterns to match against
# TreeFile-relative filenames. Any files in the TreeFile system
# that match one of these patterns will be processed by the
# CustomizationVariableCollector.
my @processFilePatterns =
(
'^texturerenderer/.+\.trt$', '^shader/.+\.sht$',
'^appearance/.+\.(apt|cmp|lmg|lod|lsb|mgn|msh|sat|pob)$'
# ---
# TEST ENTRIES: don't include these for real processing, used to test formats one-at-a-time.
# ---
# '^appearance/.+\.sat$'
# '^appearance/.+\.mgn$'
# '^shader/.+\.sht$'
# '^appearance/.+\.lsb$'
# '^appearance/.+\.lod$'
# '^appearance/.+\.apt$'
# '^appearance/.+\.msh$'
# '^appearance/.+\.cmp$'
# ---
);
CustomizationVariableCollector::collectData(@processFilePatterns);
# Handle vehicle customization steps that cannot be handled by analyzing IFF file contents.
VehicleCustomizationVariableGenerator::collectData($branch);

18
tools/configFileBuilder.pl Executable file
View File

@@ -0,0 +1,18 @@
while (<>)
{
next if (s/^cfg: // == 0);
chomp;
($section, $value) = /\[(.*)\] (.*)/;
$key{$section . "." . $value} = 1;
}
foreach (sort keys %key)
{
($section, $value) = split(/\./, $_, 2);
if ($section ne $oldSection)
{
$oldSection = $section;
print "[", $section, "]\n";
}
print "\t", $value, "\n";
}

99
tools/copyExe.btm Normal file
View File

@@ -0,0 +1,99 @@
@echo off
if not exist "copyexe.btm" goto error
if not exist ..\exe\win32 md /s ..\exe\win32
:run
echo AnimationEditor...
copy %1 ..\src\compile\win32\AnimationEditor\optimized\AnimationEditor_o.exe ..\exe\win32
echo Client...
copy %1 ..\src\compile\win32\SwgClient\optimized\SwgClient_o.exe ..\exe\win32
copy %1 ..\src\compile\win32\SwgClient\optimized\SwgClient_o.pdb ..\exe\win32
copy %1 ..\src\compile\win32\SwgClient\release\SwgClient_r.exe ..\exe\win32
copy %1 ..\src\compile\win32\SwgClient\release\SwgClient_r.pdb ..\exe\win32
copy %1 ..\src\compile\win32\SwgGodClient\optimized\SwgGodClient_o.exe ..\exe\win32
copy %1 ..\src\compile\win32\SwgGodClient\optimized\SwgGodClient_o.pdb ..\exe\win32
copy %1 ..\src\compile\win32\SwgClientSetup\release\SwgClientSetup_r.exe ..\exe\win32
echo ClientEffectEditor...
copy %1 ..\src\compile\win32\ClientEffectEditor\optimized\ClientEffectEditor_o.exe ..\exe\win32
echo PlanetWatcher...
copy %1 ..\src\compile\win32\PlanetWatcher\optimized\PlanetWatcher_o.exe ..\exe\win32
echo ParticleEditor...
copy %1 ..\src\compile\win32\ParticleEditor\optimized\ParticleEditor_o.exe ..\exe\win32
echo ShaderBuilder...
copy %1 ..\src\compile\win32\ShaderBuilder\optimized\ShaderBuilder_o.exe ..\exe\win32
echo SoundEditor...
copy %1 ..\src\compile\win32\SoundEditor\optimized\SoundEditor_o.exe ..\exe\win32
echo SwgLoadClient...
copy %1 ..\src\compile\win32\SwgLoadClient\debug\SwgLoadClient_d.exe ..\exe\win32\SwgLoadClient_d.exe
echo TerrainEditor...
copy %1 ..\src\compile\win32\TerrainEditor\optimized\TerrainEditor_o.exe ..\exe\win32
echo TextureBuilder...
copy %1 ..\src\compile\win32\TextureBuilder\optimized\TextureBuilder_o.exe ..\exe\win32
echo Viewer...
copy %1 ..\src\compile\win32\Viewer\optimized\Viewer_o.exe ..\exe\win32
echo WorldSnapshotViewer...
copy %1 ..\src\compile\win32\WorldSnapshotViewer\optimized\WorldSnapshotViewer_o.exe ..\exe\win32
echo MayaExporter...
copy %1 ..\src\compile\win32\MayaExporter\optimized\MayaExporter.mll ..\exe\win32
echo dlls...
copy %1 ..\dev\win32\*.dll ..\exe\win32
del gl_004d.dll
del gl_004r.dll
del ..\exe\win32\gl_004d.dll
del ..\exe\win32\gl_004r.dll
echo UI Tools...
copy %1 ..\src\compile\win32\UIBuilder\release\UIBuilder.exe ..\exe\win32
copy %1 ..\src\compile\win32\UIFontBuilder\release\UIFontBuilder.exe ..\exe\win32
copy %1 ..\src\compile\win32\LocalizationTool\optimized\LocalizationTool_o.exe ..\exe\win32
echo TemplateCompilers...
copy %1 ..\src\compile\win32\TemplateDefinitionCompiler\optimized\TemplateDefinitionCompiler_o.exe ..\exe\win32\TemplateDefinitionCompiler.exe
copy %1 ..\src\compile\win32\TemplateCompiler\optimized\TemplateCompiler_o.exe ..\exe\win32\TemplateCompiler.exe
echo DataTableTool...
copy %1 ..\src\compile\win32\DataTableTool\optimized\DataTableTool_o.exe ..\exe\win32\DataTableTool.exe
echo PlanetServer (Debug)...
copy %1 ..\src\compile\win32\PlanetServer\Debug\PlanetServer_d.exe ..\exe\win32\PlanetServer_d.exe
echo SwgGameServer (Debug)...
copy %1 ..\src\compile\win32\SwgGameServer\Debug\SwgGameServer_d.exe ..\exe\win32\SwgGameServer_d.exe
echo configuration files...
copy /u ..\dev\win32\*.iff ..\exe\win32
copy /u ..\dev\win32\*.tip ..\exe\win32
copy /u ..\dev\win32\*.ini ..\exe\win32
copy /u ..\dev\win32\*.snap ..\exe\win32
copy /u ..\dev\win32\*.path ..\exe\win32
copy /u ..\dev\win32\aliases.txt ..\exe\win32
copy /u ..\exe\win32\*.iff ..\dev\win32
copy /u ..\exe\win32\*.tip ..\dev\win32
copy /u ..\exe\win32\*.ini ..\dev\win32
copy /u ..\exe\win32\*.snap ..\dev\win32
copy /u ..\exe\win32\*.path ..\dev\win32
copy /u ..\exe\win32\aliases.txt ..\dev\win32
pause
goto end
:error
echo You must run this from the tools directory!
goto end
:end

220
tools/coreMemoryReport.sh Normal file
View File

@@ -0,0 +1,220 @@
#!/bin/bash -f
if [ $# != 4 ]; then
echo Usage: coreMemoryReport.sh exename corename dumpname reportname
exit 1
fi
checkTool()
{
which $1 >& /dev/null
if [ $? = 1 ]; then
echo "Could not find $1 in $PATH."
exit 1
fi
}
# check for needed tools
checkTool grep
checkTool sed
checkTool sort
checkTool uniq
checkTool gawk
checkTool objdump
checkTool addr2line
checkTool CoreMemWalker
# check gawk version, need >= 3.1 for coprocesses
awk_major=`gawk --version |grep '^GNU Awk' |sed -e '/^GNU Awk /s///' -e '/\..*$/s///'`
awk_minor=`gawk --version |grep '^GNU Awk' |sed -e '/^GNU Awk [0-9]*\./s///' -e '/\..*$/s///'`
if [ $awk_major -le 3 ]; then
if [ $awk_major -lt 3 ] || [ $awk_minor -lt 1 ]; then
echo 'GNU Awk version >= 3.1 is required.'
exit 1
fi
fi
EXE=$1
CORE=$2
DUMPNAME=$3
REPORTNAME=$4
# load the memory map for a specified object file and section type
loadMemoryMap()
{
objdump -h $1 |grep $2 >.tmpmem
ao_c=0
while read -a LINE ; do
let s=0x${LINE[3]}
let e=$s+0x${LINE[2]}
let o=0x${LINE[5]}-$s
ao_s[$ao_c]=$s
ao_e[$ao_c]=$e
ao_o[$ao_c]=$o
let ao_c=$ao_c+1
done <.tmpmem
}
# determine the offset in the file associated with the current memory map of the memory address passed in
getAddrOffset()
{
result=0
let t=$1
i=0
while [ $i -lt $ao_c ]; do
if [ $t -ge ${ao_s[$i]} ] && [ $t -lt ${ao_e[$i]} ] ; then
let result=${ao_o[$i]}+$t
break
fi
let i=$i+1
done
echo $result
}
# determine the object to search for memory manager info
MEMOBJ=`ldd $EXE |grep libsharedMemoryManager.so |sed 's/[()]//g' |gawk '{print $3}'`
if [ "$MEMOBJ" = "" ]; then
MEMOBJ=$EXE
MEMOFS=0
else
LINE=(`ldd $EXE |sed 's/[()]//g' |sort -k 4,4 |nl |gawk '{print $1, $4}' |grep libsharedMemoryManager.so`)
MEMOFS=0x`objdump -h $CORE |grep -B1 'READONLY, CODE' |grep '00000000 4' |nl |grep "^ *${LINE[0]} " |gawk '{print $5}'`
fi
# grab the mappings of memory regions in the memory manager object
echo Getting memory manager object memory map...
loadMemoryMap $MEMOBJ rodata
# determine the number of entries in the memory block call stacks
echo Determining memory block owner call stack size...
LINE=(`objdump -t $MEMOBJ |grep ' _[^G]*22MemoryManagerNamespace.*cms_allocatedBlockSize'`)
offset=`getAddrOffset 0x${LINE[0]}`
LINE=(`od -t x4 -j$offset -N4 $MEMOBJ`)
let own_size=(0x${LINE[1]}-12)/4
# grab the mappings of memory regions in the core file
echo Getting core memory map...
loadMemoryMap $CORE load
# get the address of the first memory block
echo Finding first memory block...
LINE=(`objdump -t $MEMOBJ |grep '22MemoryManagerNamespace.*ms_firstSystemAllocation'`)
let adjustedOfs=0x${LINE[0]}+$MEMOFS
offset=`getAddrOffset $adjustedOfs`
LINE=(`od -t x4 -j$offset -N4 $CORE`)
let firstAddr=0x${LINE[1]}
rm -f $DUMPNAME
echo Dumping allocated block info...
CoreMemWalker $CORE .tmpmem $firstAddr $own_size >$DUMPNAME
rm -f .tmpmem
echo Processing memory report...
cat $DUMPNAME |sed 's/^0x[0-9a-f]* //' |sort -n |uniq -c | \
gawk '
{
printf "%d %d", $1*$2, $1
for (i = 3; i <= NF; ++i)
printf " %s", $i
printf "\n"
}' | sort -n -r >.tmpdmp
rm -f .tmpresolve .tmplib*
# Determine all binaries associated with $EXE, and store their names and
# base addresses in the lib_name and lib_addr arrays respectively.
echo Determining address spaces...
lib_count=1
lib_addr[0]=0
lib_name[0]=$EXE
ldd $EXE |sed 's/[()]//g' |sort -k 4,4 |nl |gawk '{print $1, $4}' >.tmplibs
while read -a LINE ; do
lib_name[$lib_count]=${LINE[1]}
let lib_addr[$lib_count]=0x`objdump -h $CORE |grep -B1 'READONLY, CODE' |grep '00000000 4' |nl |grep "^ *${LINE[0]} " |gawk '{print $5}'`
let lib_count=$lib_count+1
done <.tmplibs
# Determine which library in the lib_name/lib_addr arrays the passed in
# address belongs to. Return the index in the array.
getLibNumber()
{
result=0
let t=$1
j=1
while [ $j -lt $lib_count ]; do
if [ ${lib_addr[$j]} -gt $t ] ; then
break
fi
let j=$j+1
done
let result=$j-1
echo $result
}
# Run through all referenced addresses, sorting them by the binary they
# belong to, and saving a file of addresses and a separate file of
# addresses relative to the binary's start address. Also fill in '??:0'
# in the resolved address cache for each address, so that every referenced
# address has an entry, and use that to prevent trying to resolve an
# address multiple times (by outputting duplicates to the per-binary
# address list files).
echo Sorting addresses by lib...
while read -a LINE ; do
# run through $LINE[2..] accumulating addresses per lib
i=2
while [ $i -lt ${#LINE[*]} ]; do
addr=${LINE[$i]}
if [ "${addr_cache[$addr]}" != "??:0" ] ; then
lib_number=`getLibNumber $addr`
let offset=addr-${lib_addr[$lib_number]}
echo $addr >> .tmplib_addr_$lib_number
echo -n "0x" >> .tmplib_ofs_$lib_number
echo "obase=16; $offset" |bc >> .tmplib_ofs_$lib_number
addr_cache[$addr]="??:0"
fi
let i=$i+1
done
done <.tmpdmp
# Resolve all addresses referenced in the report, batched by which binary
# the address belongs to.
echo Resolving Addresses...
i=0
while [ $i -lt $lib_count ]; do
if [ -e .tmplib_ofs_$i ]; then
addr2line -s -e ${lib_name[$i]} `cat .tmplib_ofs_$i` >.tmpresolve
j=0
while read -a LINE ; do
resolved[$j]=${LINE[*]}
let j=$j+1
done <.tmpresolve
j=0
while read -a LINE ; do
addr_cache[${LINE[*]}]=${resolved[$j]}
let j=$j+1
done <.tmplib_addr_$i
fi
let i=$i+1
done
# Generate the final report file, by looking up all but the first 2 fields of
# everything in .tmpdmp in the resolved address cache.
echo Generating Report...
rm -f $REPORTNAME
while read -a LINE ; do
echo -n "${LINE[0]} ${LINE[1]}" >> $REPORTNAME
i=2
while [ $i -lt ${#LINE[*]} ]; do
addr=${LINE[$i]}
echo -n " ${addr_cache[$addr]}($addr)" >> $REPORTNAME
let i=$i+1
done
echo >> $REPORTNAME
done <.tmpdmp
rm -f .tmpdmp .tmpresolve .tmplib*
echo Done!

89
tools/coremail.pl Executable file
View File

@@ -0,0 +1,89 @@
#!/usr/bin/perl
die "usage: coremail.pl original_core_directory save_core_directory email_to [... email_to]\n" if (@ARGV < 3);
$coreDirectory = shift;
$saveDirectory = shift;
# pick a name for the backup file
open(DATE, "date \"+%Y%m%d_%H%M\" |");
$date = <DATE>;
chomp $date;
close(DATE);
# make the destination directory
mkdir($saveDirectory);
# search for new core files
$cores = 0;
opendir(DIR, $coreDirectory) || die "could not open directory $_\n";
@files = readdir(DIR);
closedir(DIR);
foreach (@files)
{
if (/core\./)
{
$cores += 1;
$new = $_;
$new =~ s/\./\.$date\./;
system("mv $coreDirectory/$_ $saveDirectory/$new");
$exe = "";
# open(GDB1, "gdb -batch -c $saveDirectory/$new |");
# while (<GDB1>)
# {
# chomp;
# $exe = $_ if (s/^Core was generated by \`// && s/ .*//);
# }
# close(GDB1);
# push(@cores, "$saveDirectory/$new\t$exe\n");
# if ($exe ne "")
# {
# open(BT, ">/tmp/gdb.bt");
# print BT "bt\n";
# close(BT);
# open(GDB2, "gdb $coreDirectory/$exe $saveDirectory/$new -batch -x /tmp/gdb.bt |");
# while (<GDB2>)
# {
# push(@cores, "\t" . $_);
# }
# close(GDB2);
# unlink("/tmp/gdb.bt");
# }
# else
# {
# open(FILE, "file $saveDirectory/$new |");
# close(FILE);
# while (<FILE>)
# {
# push(@cores, "\t" . $_);
# }
# close(FILE);
# }
system("gzip $saveDirectory/$new");
}
}
# send out mail if necessary
if ($cores)
{
# get the host name
open(HOSTNAME, "hostname -s |");
$hostname = <HOSTNAME>;
close(HOSTNAME);
chomp $hostname;
# send the email
$s = "";
$s = "s" if ($cores > 1);
open(MAIL, "| mail -s \"[cores] $hostname has $cores new core file$s\" " . join(" ", @ARGV), );
print MAIL join("", @cores);
close(MAIL);
}

97
tools/crashCompare.pl Executable file
View File

@@ -0,0 +1,97 @@
#!/usr/bin/perl -w
use strict;
my (%keys, %rows);
my (@files, $file);
my $row = 0;
my $spaced = 0;
die "$0: Usage: $0 <directory>\n" unless(@ARGV);
if($ARGV[0] eq "-s")
{
$spaced=1;
shift;
}
opendir(DIR, "$ARGV[0]") || die "$0: Can't open directory $ARGV[0]\n";
while($_ = readdir(DIR))
{
next unless($_ =~ m%\.txt$% && $_ !~ m%^_%);
push(@files, $_);
}
closedir(DIR);
exit if($#files == -1);
foreach $file(@files)
{
open(INPUT, "<$ARGV[0]/$file") || die "$0: Can't open $_: $!\n";
$keys{"z-filename"}=1;
while(<INPUT>)
{
$/="\n\n";
my $trash = <INPUT>;
$trash = <INPUT>;
$/="\n";
while($_ = <INPUT>)
{
chomp;
if(/:/)
{
my($key, $value) = split(/:/, $_, 2);
$value =~ s%\s+% %g;
$value =~ s%^\s+%%;
$value =~ s%\s+$%%;
my @elements = split(/\s/, $value);
if($spaced && $#elements > 0)
{
my $origkey = $key;
for(0 .. $#elements)
{
$key = $origkey . ($_+1);
$rows{$row}{$key} = $elements[$_];
$keys{$key} = 1;
}
}
else
{
$rows{$row}{$key} = $value;
$keys{$key} = 1;
}
}
$rows{$row}{"z-filename"} = $file;
}
}
close(INPUT);
$row++;
}
print join("\t", sort(keys(%keys)));
print "\n";
$row--;
my $colcount;
for(0..$row)
{
$colcount = 1;
if (defined $rows{$_})
{
my %current = %{$rows{$_}};
foreach my $column (sort(keys(%keys)))
{
if(defined($current{$column}))
{
print $current{$column};
}
else
{
print "-";
}
print "\t" unless(scalar(keys(%keys)) == $colcount);
$colcount++;
}
print "\n";
}
}

View File

@@ -0,0 +1,96 @@
# Call with the following args:
# [-s <groupSize>] filename1 [filename 2 [...]]
# Where:
# <groupSize> defines the size of the square within which nearby entries will be considered to be at the same location.
use strict;
my $debug = 0;
my $groupSize = 100.0;
my %crashCountByLocation;
sub sign
{
my $value = shift;
if ($value >= 0)
{
return 1;
}
else
{
return -1;
}
}
sub quantizeCoordinate
{
my $coordinate = shift;
return int(abs($coordinate)/$groupSize) * $groupSize * sign($coordinate);
}
sub addCrashLocation
{
my $terrainName = shift;
my $x = quantizeCoordinate(shift);
my $y = shift;
my $z = quantizeCoordinate(shift);
my $key = $terrainName . ':' . $x . ':' . $z;
++$crashCountByLocation{$key};
}
sub printCrashSummary
{
printf("count\t%25s: %6s %6s\n\n", 'terrain file', 'x', 'z');
# Sort entries by count, starting with highest.
foreach my $key (sort { $crashCountByLocation{$b} <=> $crashCountByLocation{$a} } keys %crashCountByLocation)
{
my $count = $crashCountByLocation{$key};
my @keyData = split(/:/, $key);
my $terrain = $keyData[0];
my $x = $keyData[1];
my $z = $keyData[2];
printf("%d\t%25s: %6d %6d\n", $count, $terrain, $x, $z);
}
}
# Handle options.
if (defined($ARGV[0]) && ($ARGV[0] eq '-s'))
{
shift;
$groupSize = shift;
}
print "group size: $groupSize\n" if $debug;
# Process Files
my $terrain;
my $x;
my $y;
my $z;
while (<>)
{
chomp();
# Check for terrain
if (s/^Terrain:\s*//)
{
$terrain = $_;
}
elsif (m/^Player:\s*(\S+)\s+(\S+)\s+(\S+)/)
{
$x = $1;
$y = $2;
$z = $3;
# This line depends on the Player entry coming after the Terrain entry in a .txt file.
addCrashLocation($terrain, $x, $y, $z);
}
}
printCrashSummary;

182
tools/createClientOTs.pl Executable file
View File

@@ -0,0 +1,182 @@
###################################################
#
# createClientOTs.pl
# authored by Eric Sebesta (esebesta@soe.sony.com
#
# Purpose: When run in a directory, it generates, and submits to
# perforce a basic set of object templates (client and server
# based on the files in the directory, which must be appearances.
# The user must pass in client and server tdf files so that we can
# generate object templates appropriate for the given appearances.
#
###################################################
use Cwd;
#initialize an array with all the possible extensions a valid appearance would have
#we use this array to check that a given file is actually an appearance
@appearanceExtensions = (".lod", ".cmp", ".msh", ".sat");
#the template compiler must be run from the area where the tpf files should live, so make
#sure they are in a currently accepted location for them
$requiredSourceDir = "plt.shared\loc.shared\compiled\game\object";
$requiredSourceDirFront = "plt.shared/loc.shared/compiled/game/object";
#users must pass in 2 parameters, the appearance directory and the tdf file used to generate the tpfs
if (scalar(@ARGV) != 2)
{
die "usage: createClientOTs <appearance directory> <TDF> \nRequire 2 parameters, received $numArgs\n";
}
#if(!cwd() =~ "sys.client")
#{
# die "must be in client template directory!\n";
#}
#TODO this isn't working?
#check the current directory against the required ones
if(!cwd() =~ $requiredSourceDir)
{
if(!cwd() =~ $requiredSourceDirFront)
{
print "not in correct dir, must be in dsrc\"\\<blah blah blah>\\game\\object\" or below\n";
die;
}
}
#get the various command line parameters
my $appearanceDir = $ARGV[0];
print "appearance directory is $appearanceDir\n";
$TDF = $ARGV[1];
print "Tdf is $TDF\n";
#we're all done with initial listing, delimite with a line
print "\n";
#make sure the appearance directory exists before proceeding, since we'll want to open all those files
-e $appearanceDir or die "ERROR: appearance directory does not compute, I mean exist\n";
#read the files from the current directory
opendir CURRENTDIR, $appearanceDir or die "ERROR: can't read current directory, bad: $1";
my @files = readdir CURRENTDIR;
closedir CURRENTDIR;
#process each file, building, editing, compiling, and submitting the tpf and iff file
foreach $file (@files)
{
print "processing $file...\n";
#validate that the current file is an appearance
my $found = 0;
foreach $ext (@appearanceExtensions)
{
if($file =~ /$ext/)
{
$found = 1;
}
}
if($found == 0)
{
print " WARNING: not an appearance file, skipping\n"
}
#okay, the file exists and is an appearance, and we are in a directory to drop tpf's into, go for it
createOT($file);
#one line seperator between files
print "\n";
}
############################################################################
sub createOT #11/08/01 10:58:AM
############################################################################
{
#the new client template name is passed in as a parameter
my $appearanceFileName = @_[0];
#turn the filename into a short client template name (i.e. remove any pathing info and remove the extension)
$appearanceFileName =~ m/^(.*)\./;
my $base = $1;
my @args = ("templateCompiler", "-generate", $TDF, $base);
print "@args...";
if(system(@args) != 0)
{
print "\ncouldn't run templatecompiler for template, skipping)";
return;
}
else
{
print "success\n";
}
#now get the actual tpf filename
my $templateFileName = $base . ".tpf";
#the base template has been generated, now fill in the appearance name
my $TEMPLATE = $templateFileName;
if (-e $TEMPLATE)
{
#build the new line we want to write (the new appearance name)
my $newLine = "appearanceFilename = \"appearance\\" . $appearanceFileName . "\"\n";
#open the new tpf file for read, so we can set the appearance name
open (TEMPLATE, '<' . $templateFileName) or die "failed to open original tpf file for editing\n";
#open a temporary file for us to write the new contents into
my $tempPathname = $templateFileName . '.tmp';
open (TEMP, '>' . $tempPathname) or die "failed to open dest filename for writing [$destPathname]\n";
#search the tpf the appearance line
while ($line = <TEMPLATE>)
{
if($line =~ "appearanceFilename = ")
{
#output our new line with the appearance name
print TEMP $newLine;
}
else
{
#otherwise, write back out the original contents
print TEMP $line;
}
}
#close all filehandles
close TEMPLATE;
close TEMP;
# rename dest filename to source filename, clobbering the original source
rename $tempPathname, $templateFileName;
}
else
{
print "\ncouldn't client template file does not exist, skipping....\n";
return;
}
@args = ("templateCompiler", "-compile", $templateFileName);
print "@args...";
if(system(@args) != 0)
{
print "\ncouldn't run templatecompiler -compile for template, skipping)";
return;
}
else
{
print "success\n";
}
@args = ("templateCompiler", "-submit", $templateFileName);
print "@args...";
print "not run\n";
#if(system(@args) != 0)
#{
# print "couldn't run templatecompiler -submit for client template, skipping)";
# return;
#}
#else
#{
# print "success\n";
#}
} ##createOT

166
tools/createServerOTs.pl Executable file
View File

@@ -0,0 +1,166 @@
###################################################
#
# createServerOTs.pl
# authored by Eric Sebesta (esebesta@soe.sony.com
#
# Purpose: When run in a directory, it generates, and submits to
# perforce a basic set of object templatesbased on the files in the
# directory, which must be appearances.
# The user must pass in client and server tdf files so that we can
# generate object templates appropriate for the given appearances.
#
###################################################
use Cwd;
#initialize an array with all the possible extensions a valid appearance would have
#we use this array to check that a given file is actually an appearance
#@appearanceExtensions = (".lod", ".cmp", ".msh", ".sat");
#the template compiler must be run from the area where the tpf files should live, so make
#sure they are in a currently accepted location for them
$requiredSourceDir = "plt.shared\loc.shared\compiled\game\object";
$requiredSourceDirFront = "plt.shared/loc.shared/compiled/game/object";
#users must pass in 3 parameters, the appearance directory and the tdf file used to generate the tpfs
if (scalar(@ARGV) != 3)
{
die "usage: createServerOTs <clientTemplateRelative dir, i.e. \"tangible\"> <appearance dir> <TDF> \nRequire 2 parameters, received $numArgs\n";
}
#if(!cwd() =~ "sys.server")
#{
# die "must be in server template directory!\n";
#}
#TODO this isn't working?
#check the current directory against the required ones
if(!cwd() =~ $requiredSourceDir)
{
if(!cwd() =~ $requiredSourceDirFront)
{
print "not in correct dir, must be in dsrc\"\\<blah blah blah>\\game\\object\" or below\n";
die;
}
}
#get the various command line parameters
my $clientTemplateRelativeDir = $ARGV[0];
print "client relative directory is $clientTemplateRelativeDir\n";
my $appearanceDir = $ARGV[1];
print "appearance directory is $appearanceDir\n";
$TDF = $ARGV[2];
print "Tdf is $TDF\n";
#we're all done with initial listing, delimite with a line
print "\n";
#make sure the appearance directory exists before proceeding, since we'll want to open all those files
#-e $appearanceDir or die "ERROR: appearance directory does not compute, I mean exist\n";
#read the files from the current directory
opendir CURRENTDIR, $appearanceDir or die "ERROR: can't read current directory, bad: $1";
my @files = readdir CURRENTDIR;
closedir CURRENTDIR;
#process each file, building, editing, compiling, and submitting the tpf and iff file
foreach $file (@files)
{
print "processing $file...\n";
createOT($file);
#one line seperator between files
print "\n";
}
############################################################################
sub createOT #11/08/01 10:58:AM
############################################################################
{
#the new server template name is passed in as a parameter
my $fileName = @_[0];
#turn the filename into a short server template name (i.e. remove any pathing info and remove the extension)
$fileName =~ m/^(.*)\./;
my $base = $1;
my @args = ("templateCompiler", "-generate", $TDF, $base);
print "@args...";
if(system(@args) != 0)
{
print "\ncouldn't run templatecompiler for template, skipping)";
return;
}
else
{
print "success\n";
}
#now get the actual iff filename
my $templateSourceFileName = $base . ".tpf";
my $compiledClientFileName = $base . ".iff";
#the base template has been generated, now fill in the client template name
my $TEMPLATE = $templateSourceFileName;
if (-e $TEMPLATE)
{
#build the new line we want to write (the new appearance name
$newLine = "clientTemplate = \"" . $clientTemplateRelativeDir . "\\" . $compiledClientFileName . "\"\n";
#open the new tpf file for read, so we can set the appearance name
open (TEMPLATE, '<' . $templateSourceFileName) or die "failed to open original tpf file for editing\n";
#open a temporary file for us to write the new contents into
my $tempPathname = $templateSourceFileName . '.tmp';
open (TEMP, '>' . $tempPathname) or die "failed to open dest filename for writing [$destPathname]\n";
#search the tpf the appearance line
while ($line = <TEMPLATE>)
{
if($line =~ "clientTemplate =")
{
#output our new line with the client template name
print TEMP $newLine;
}
else
{
#otherwise, write back out the original contents
print TEMP $line;
}
}
#close all filehandles
close TEMPLATE;
close TEMP;
# rename dest filename to source filename, clobbering the original source
rename $tempPathname, $templateSourceFileName;
}
@args = ("templateCompiler", "-compile", $templateSourceFileName);
print "@args...";
if(system(@args) != 0)
{
print "\ncouldn't run templatecompiler -compile for template, skipping)";
return;
}
else
{
print "success\n";
}
@args = ("templateCompiler", "-submit", $templateSourceFileName);
print "@args...";
print "not run\n";
#if(system(@args) != 0)
#{
# print "couldn't run templatecompiler -submit for client template, skipping)";
# return;
#}
#else
#{
# print "success\n";
#}
} ##createOT

367
tools/custTool.pl Executable file
View File

@@ -0,0 +1,367 @@
# ======================================================================
#
# Customization Variable Tool
# Copyright 2003, Sony Online Entertainment, Inc.
#
# ======================================================================
use strict;
use File::Find;
use POSIX qw(strftime);
# ======================================================================
# Constants
my $maxAllowableVariableId = 127;
my $dataFormatVersionNumber = 1;
my $firstAssignableId = 1;
# Names of customization variables.
my %countsByVariableName;
# Name to id assignment.
my %idsByVariableName;
my $newVariableCount = 0;
# Action options.
my $doPrintReport = 0;
my $doGenerateMifMapFile = 0;
# Report printing options.
my $printTpfFileNames = 0;
my $printSortByCount = 0;
my $printSortByName = 0;
my $reverseSort = 0;
# Id map file generation options.
my $mifFileName = "";
my $mifFileMustExist = 1;
my $debug = 0;
# ======================================================================
# SUBROUTINES
# ======================================================================
# ======================================================================
sub processArgs
{
# Process args. Args must come first.
while (defined($ARGV[0]) && ($ARGV[0] =~ m/^-([a-zA-Z]*)$/))
{
if ($1 eq "i")
{
$doPrintReport = 1;
}
elsif ($1 eq "g")
{
$doGenerateMifMapFile = 1;
}
elsif ($1 eq "F")
{
# Support first-time mif file generation, but force it to be a flag
# so the default is to die if not explicity specified and the mif
# file doesn't exist.
$mifFileMustExist = 0;
}
elsif ($1 eq "o")
{
die "-o option requires a filename to be specified after it (e.g. -o customization_id_manager.mif)\n" if !defined($ARGV[1]);
$mifFileName = $ARGV[1];
shift @ARGV;
die "filename [$mifFileName] should end in extension \".mif\"\n" if !($mifFileName =~ m/\.mif$/);
}
elsif ($1 eq "t")
{
$printTpfFileNames = 1;
}
elsif ($1 eq "c")
{
$printSortByCount = 1;
}
elsif ($1 eq "n")
{
$printSortByName = 1;
}
elsif ($1 eq "r")
{
$reverseSort = 1;
}
elsif ($1 eq "d")
{
$debug = 1;
}
shift @ARGV;
}
#-- Ensure we do at least some activity. Assume report generation is default.
if (($doPrintReport == 0) && ($doGenerateMifMapFile == 0))
{
$doPrintReport = 1;
}
#-- Ensure we'll print at least some output. Default is print-by-count if no printing option is specified.
if (($printSortByCount == 0) && ($printSortByName == 0))
{
$printSortByCount = 1;
}
}
# ======================================================================
sub findFileHandler
{
#-- Check if this is a TPF file.
if (m/^.*\.tpf$/)
{
#-- Indicate file we're testing.
print "Processing [$File::Find::name].\n" if $printTpfFileNames;
#-- Open the TPF file.
open(FILE, $_);
#-- Scan all variable names within the TPF file.
while (<FILE>)
{
chomp();
if (m/variableName="([^"]*)\"/) # last double-quote escaped for Emacs font-lock mode.
{
$countsByVariableName{$1}++;
}
}
#-- Close the file.
close(FILE);
}
}
# ======================================================================
sub collectCustomizationVariableData
{
# Setup directories to check.
@ARGV = ('.') if !defined($ARGV[0]);
# Do the find to scan in all TPF filenames.
find (\&findFileHandler, @ARGV);
}
# ======================================================================
sub printReport
{
# Handle printing sorted by name.
if ($printSortByName)
{
my @sortedKeys = sort keys(%countsByVariableName);
@sortedKeys = reverse @sortedKeys if $reverseSort;
print "Variable names sorted by name (" . @sortedKeys . " unique variable names):\n";
print "variable name\tcount\n";
foreach my $variableName (@sortedKeys)
{
my $count = $countsByVariableName{$variableName};
print "$variableName\t$count\n";
}
print "\n";
}
if ($printSortByCount)
{
my @sortedKeys = sort {$countsByVariableName{$b} <=> $countsByVariableName{$a}} keys(%countsByVariableName);
@sortedKeys = reverse @sortedKeys if $reverseSort;
print "Variable names sorted by name (" . @sortedKeys . " unique variable names):\n";
print "count\tvariable name\n";
foreach my $variableName (@sortedKeys)
{
my $count = $countsByVariableName{$variableName};
print "$count\t$variableName\n";
}
print "\n";
}
}
# ======================================================================
sub collectExistingVariableNameAssignments
{
open(MIF_FILE, $mifFileName) or die "failed to open specified mif file [$mifFileName]: $!";
my $nextAssignmentId = $firstAssignableId;
my $expectingId = 1;
while (<MIF_FILE>)
{
chomp();
if (m/int16\s+(\d+)\s*$/)
{
# Ensure we're expecting a new id.
die "error: file [$mifFileName] appears malformed, out of order int16/cstring declarations.\n" if !$expectingId;
$expectingId = 0;
$nextAssignmentId = $1;
}
elsif (m/cstring\s+\"([^\"]+)\"\s*$/)
{
# Ensure we're expecting a variable name.
die "error: file [$mifFileName] appears malformed, out of order int16/cstring declarations.\n" if $expectingId;
$expectingId = 1;
# Add new variable name. It is associated with $nextAssignmentId collected previously.
$idsByVariableName{$1} = $nextAssignmentId;
print "<existing: mapping variable name [$1] to [$nextAssignmentId]>\n" if $debug;
}
}
close(MIF_FILE);
}
# ======================================================================
sub writeMifFile
{
open(MIF_FILE, ">$mifFileName") or die "failed to open mif file [$mifFileName] for writing: $!";
my $timeString = strftime "%a %b %e %H:%M:%S %Y", localtime(time());
print MIF_FILE "// ======================================================================\n";
print MIF_FILE "// Output generated by Perl script \"$0\"\n";
print MIF_FILE "// Generation time: $timeString\n";
print MIF_FILE "//\n";
print MIF_FILE "// Do not hand-edit this file! It is generated by the build process.\n";
print MIF_FILE "// Changing values from a previous run without a database update will\n";
print MIF_FILE "// invalidate database-stored customization data.\n";
print MIF_FILE "// ======================================================================\n\n";
print MIF_FILE "form \"CIDM\"\n";
print MIF_FILE "{\n";
print MIF_FILE "\tform \"0001\"\n";
print MIF_FILE "\t{\n";
print MIF_FILE "\t\tchunk \"DATA\"\n";
print MIF_FILE "\t\t{\n";
foreach my $variableName (sort { $idsByVariableName{$a} <=> $idsByVariableName{$b} } keys %idsByVariableName)
{
print MIF_FILE "\t\t\tint16\t$idsByVariableName{$variableName}\n";
print MIF_FILE "\t\t\tcstring\t\"$variableName\"\n\n";
}
print MIF_FILE "\t\t}\n";
print MIF_FILE "\t}\n";
print MIF_FILE "}\n";
close(MIF_FILE);
print "<success: wrote new customization id manager data file [$mifFileName]>\n" if $debug;
}
# ======================================================================
sub assignNewVariableIds
{
# Setup starting id: should be the same as # entries in assignment map.
my @sortedValues = sort {$b <=> $a} values %idsByVariableName;
my $nextAssignmentId = $firstAssignableId;
$nextAssignmentId = ($sortedValues[0] + 1) if defined($sortedValues[0]);
print "<firstNewId: $nextAssignmentId>\n" if $debug;
# Process new IDs sorted by frequency from most to least, causing
# lower ID values to be assigned to higher-frequency items. This
# could be useful if some of the lower frequency items are really
# typos and need to be shuffled around.
foreach my $variableName (sort {$countsByVariableName{$b} <=> $countsByVariableName{$a}} keys %countsByVariableName)
{
# Check if variable is assigned yet.
if (!defined($idsByVariableName{$variableName}))
{
$idsByVariableName{$variableName} = $nextAssignmentId;
print "<new: mapping variable name [$variableName] to [$nextAssignmentId]>\n" if $debug;
++$nextAssignmentId;
++$newVariableCount;
}
}
}
# ======================================================================
sub generateMifMapFile
{
# Collect existing mif map assignments.
if (-f $mifFileName)
{
collectExistingVariableNameAssignments();
}
elsif ($mifFileMustExist)
{
if (length($mifFileName) < 1)
{
die "error: must specify filename for existing and output mif file with the -o flag.\n";
}
else
{
die "error: Customization id manager file must exist to preserve existing mappings.\nerror: Failed to find [$mifFileName].\nerror: Use -F for first-time file generation, don't do this unless you know what you're doing!\n";
}
}
# Generate assignments for non-populated but existing customization variables.
assignNewVariableIds();
# Check if we've exceeded the max assignable id value.
my @sortedAssignedIds = sort {$a <=> $b} values %idsByVariableName;
my $idCount = @sortedAssignedIds;
if ($idCount > 0)
{
my $maxAssignedId = $sortedAssignedIds[$idCount - 1];
print "<maxAssignedId: $maxAssignedId>\n" if $debug;
if ($maxAssignedId > $maxAllowableVariableId)
{
die "error: new unassigned customization variable ids needed but no more room.\nerror: Either unused names must be removed with database remapping or a new data format must be implemented.\nNeed id of $maxAssignedId but max allowable is $maxAllowableVariableId for format version $dataFormatVersionNumber.\n";
}
}
# Write new mif file if any changes.
if ($newVariableCount > 0)
{
writeMifFile();
}
else
{
print "skipping file generation: no new customization variable names found.\n";
}
}
# ======================================================================
# PROGRAM STARTING POINT.
# ======================================================================
# Program starts here.
{
# Handle arguments.
processArgs();
# Collect customization variable data.
collectCustomizationVariableData();
# Handle report generation.
if ($doPrintReport)
{
printReport();
}
# Handle mif file generation.
if ($doGenerateMifMapFile)
{
generateMifMapFile();
}
}
# ======================================================================

437
tools/custUpgrade.pl Executable file
View File

@@ -0,0 +1,437 @@
# ======================================================================
#
# custUpgrade.pl
# Copyright 2003 Sony Online Entertainment, Inc.
# All Rights Reserved.
#
# ======================================================================
# Used to upgrade SWG customization data from an older database format
# to a newer database format. Note the exact upgrade logic needed will
# be different in any upgrade situation, but this should be a good template
# for most of the code in the event of another customization data upgrade
# some time in the future.
# Perl modules DBI and DBD::Oracle must be installed to run this tool. See www.perl.com for info on getting these modules.
# You must have PERL5LIB (or PERLLIB) set to your mapping for //depot/swg/current/tools/perllib.
use Customization;
use DBI;
use strict;
# ======================================================================
# Module Globals
# ======================================================================
#options
my $userName = "";
my $password = "changeme";
my $databaseName = "swodb";
my $debug = 0;
my $noChanges = 0;
my $doUpgrade = 0;
my $commitCount = 0;
my $limitRowCount = 0;
my $progressStep = 0;
my $defaultFilename = '../dsrc/sku.0/sys.shared/compiled/game/customization/customization_id_manager.mif';
my $customizationIdManagerFilename = $defaultFilename;
# ======================================================================
sub printHelp
{
print "Calling syntax:\n";
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";
print "Option description:\n";
print "\t-u: specifies the name of the user for the Oracle database.\n";
print "\t-p: [optional] specifies the password for the user of the Oracle database. Default: changeme.\n";
print "\t-D: [optional] specifies the database to attach to. Default: swodb.\n";
print "\t-d: [optional] turn on extensive debug-level output.\n";
print "\t-n: [optional] do not make changes to the database, just print what would have happened.\n";
print "\t-U: [optional] Upgrade customization data in the database.\n";
print "\t-c: [optional] commit every 'commit count' number of rows processed, or 0 for single commit at the end. Default: 0.\n";
print "\t-l: [optional] limit database processing to first <limit row count> rows or 0 for no limit. Default: 0.\n";
print "\t-m: [optional] specify path to CustomizationIdManager's mif version of initialization file. Default: $defaultFilename\n";
print "\t-s: [optional] print a progress line every progressStep percent or 0 if no output. Default: 0.\n";
print "\t-h: [optional] print this help info.\n";
}
# ======================================================================
sub collectOptions
{
my $showHelp = 0;
my $exitCode = 0;
while (defined($ARGV[0]) && ($ARGV[0] =~ m/^-(.*)$/))
{
if ($1 eq 'u')
{
# Grab username.
if (@ARGV < 2)
{
print "-u option missing <database username> specification.\n";
$exitCode = 1;
last;
}
$userName = $ARGV[1];
print "<username: $userName>\n" if $debug;
# Skip past arg.
shift @ARGV;
}
elsif ($1 eq 'p')
{
# Grab password.
if (@ARGV < 2)
{
print "-p option missing <password> specification.\n";
$exitCode = 1;
next;
}
$password = $ARGV[1];
print "<password: $password>\n" if $debug;
# Skip past arg.
shift @ARGV;
}
elsif ($1 eq 'D')
{
# Grab database name.
if (@ARGV < 2)
{
print "-D option missing <database> specification.\n";
$exitCode = 1;
next;
}
$databaseName = $ARGV[1];
print "<database: $databaseName>\n" if $debug;
# Skip past arg.
shift @ARGV;
}
elsif ($1 eq 'd')
{
$debug = 1;
$Customization::Debug = 1;
}
elsif ($1 eq 'n')
{
$noChanges = 1;
}
elsif ($1 eq 'U')
{
$doUpgrade = 1;
}
elsif ($1 eq 'h')
{
$showHelp = 1;
}
elsif ($1 eq 'c')
{
# Grab commit count.
if (@ARGV < 2)
{
print "-c option missing <commit count> specification.\n";
$exitCode = 1;
next;
}
$commitCount = $ARGV[1];
print "<commit count: $commitCount>\n" if $debug;
# Skip past arg.
shift @ARGV;
}
elsif ($1 eq 'l')
{
# Grab commit count.
if (@ARGV < 2)
{
print "-l option missing <limit row count> specification.\n";
$exitCode = 1;
next;
}
$limitRowCount = $ARGV[1];
print "<limitRowCount: $limitRowCount>\n" if $debug;
# Skip past arg.
shift @ARGV;
}
elsif ($1 eq 'm')
{
# Grab commit count.
if (@ARGV < 2)
{
print "-m option missing <CustomizationIdManager MIF file> specification.\n";
$exitCode = 1;
next;
}
$customizationIdManagerFilename = $ARGV[1];
print "<customizationIdManagerFilename: $customizationIdManagerFilename\n" if $debug;
# Skip past arg.
shift @ARGV;
}
elsif ($1 eq 's')
{
# Grab commit count.
if (@ARGV < 2)
{
print "-s option missing <progressStepPercent> specification.\n";
$exitCode = 1;
next;
}
$progressStep = $ARGV[1];
print "<progressStep: $progressStep>\n" if $debug;
# Skip past arg.
shift @ARGV;
}
else
{
warn "unknown option [$1].";
$exitCode = 1;
}
# Process next argument.
shift @ARGV;
}
# Check for missing options.
if (length $userName < 1)
{
print "missing -u username option.\n";
$exitCode = 1;
}
# Show help as needed.
if ($showHelp || ($exitCode != 0))
{
printHelp();
exit($exitCode);
}
}
# ======================================================================
# input: old-style customization ascii string.
# output: new-style customization binary data (as string) (unescaped --- can contain embedded NULLs).
# ======================================================================
sub convertOldToNew
{
# Get the string.
my $oldString = shift;
# fill directory contents from old string.
my %variableInfo;
my $rc = getVariableInfoFromOldString(%variableInfo, $oldString);
if (!$rc)
{
warn "convertOldToNew:failed to get variable info from old-style customization data string [$oldString]\n";
return "";
}
return createNewDataFromVariableInfo(%variableInfo);
}
# ======================================================================
sub doUpgrade
{
my $returnCode;
# Open the database connection.
my $dbHandle = DBI->connect("dbi:Oracle:$databaseName", $userName, $password, { RaiseError => 1, AutoCommit => 0 });
error("failed to open database: [$DBI::errstr]") if !defined($dbHandle);
print "<connection: opened connection to database [$databaseName] as user [$userName] successfully.>\n" if $debug;
# Find # rows that match our criteria of non-zero-length customization data.
my $totalRowCount = 0;
{
my $statementHandle = $dbHandle->prepare("SELECT COUNT(*) FROM tangible_objects WHERE LENGTH(appearance_data) > 0") or die $dbHandle->errstr;
$statementHandle->execute() or die $statementHandle->errstr;
my @row = $statementHandle->fetchrow_array;
die($statementHandle->errString) if !@row;
$totalRowCount = $row[0];
print "<totalRowCount: $totalRowCount>\n" if $debug;
}
# Progress bar uses limitRowCount or totalRowCount depending on whether row limiting is in effect.
my $progressTotalRowCount = $totalRowCount;
if (($limitRowCount > 0) && ($limitRowCount < $totalRowCount))
{
$progressTotalRowCount = $limitRowCount;
}
# Process rows.
my $uncommittedRowCount = 0;
my $totalCommittedRowCount = 0;
my $processedRowCount = 0;
my $failedRowCount = 0;
my $sumOldStringSize = 0;
my $sumNewDataSize = 0;
my $sumNewStringSize = 0;
my $lastPrintedPercent = 0;
{
# Prepare the SELECT statement.
my $statementHandle = $dbHandle->prepare("SELECT object_id, appearance_data FROM tangible_objects WHERE LENGTH(appearance_data) > 0") or die $dbHandle->errstr;
$statementHandle->execute() or die $statementHandle->errstr;
# Prepare the UPDATE statement.
my $updateStatementHandle = $dbHandle->prepare("UPDATE tangible_objects SET appearance_data = ? WHERE object_id = ?") or die $dbHandle->errstr;
while (my @row = $statementHandle->fetchrow_array)
{
# Validate row entry count.
die "Returned row has " . @row . "entries, expecting 2." if (@row != 2);
++$processedRowCount;
# Retrieve object id and old customization data.
my $objectId = $row[0];
my $oldCustomizationString = $row[1];
print "<row: num=[$processedRowCount] id=[$objectId]: string=[$oldCustomizationString]>\n" if $debug;
# Keep track of old customization string size.
$sumOldStringSize += length $oldCustomizationString;
# Convert the row.
my $newCustomizationData = convertOldToNew($oldCustomizationString);
my $newDataLength = length $newCustomizationData;
if (!defined($newCustomizationData) || ($newDataLength < 1))
{
++$failedRowCount;
print STDERR "failed to convert old customization data [$oldCustomizationString] (total failed rows=$failedRowCount).\n";
}
else
{
# Track new unescaped binary data length.
$sumNewDataSize += $newDataLength;
# Convert binary data to escaped string form.
my $newCustomizationString = escapeBinaryData($newCustomizationData);
# Track new escaped string data length.
my $newStringLength = length $newCustomizationString;
if (!defined($newCustomizationString) || ($newStringLength < 1))
{
++$failedRowCount;
print STDERR "failed to convert new binary customization data [$newCustomizationData] to string (total failed rows=$failedRowCount).\n";
}
else
{
$sumNewStringSize += length $newCustomizationString;
# Update the database with new entry.
if (!$noChanges)
{
# Execute the update.
$updateStatementHandle->execute($newCustomizationString, $objectId) or die $statementHandle->errstr;
# Check if we should commit.
++$uncommittedRowCount;
if (($commitCount != 0) && ($uncommittedRowCount >= $commitCount))
{
# Commit now.
my $returnCode = $dbHandle->commit or die $dbHandle->errstr;
$totalCommittedRowCount += $uncommittedRowCount;
print "<commit: $uncommittedRowCount rows committed now, $processedRowCount total, returnCode=$returnCode.>\n" if $debug;
$uncommittedRowCount = 0;
}
}
else
{
print "<update: would do UPDATE tangible_objects SET appearance_data = (" . $newStringLength . " byte string) WHERE object_id = [$objectId]>\n" if $debug;
}
}
}
# Handle progress monitoring.
if ($progressStep > 0)
{
my $progressPercent = 100.0 * $processedRowCount / $progressTotalRowCount;
if ($progressPercent >= ($lastPrintedPercent + $progressStep))
{
$lastPrintedPercent = $progressPercent;
printf("progress: %d%% complete.\n", $lastPrintedPercent);
}
}
# Handle row limiting.
if (($limitRowCount > 0) && ($processedRowCount >= $limitRowCount))
{
print "<limitRowCount: specified row count limit [$limitRowCount] hit, finishing now.>\n" if $debug;
last;
}
}
}
# Do final commit.
if (!$noChanges)
{
my $returnCode = $dbHandle->commit or die $dbHandle->errstr;
$totalCommittedRowCount += $uncommittedRowCount;
print "<commit: $uncommittedRowCount rows committed now, $processedRowCount total, returnCode=$returnCode.>\n" if $debug;
$uncommittedRowCount = 0;
}
# Close the database connection.
$returnCode = $dbHandle->disconnect or warn $dbHandle->errstr;
print "<disconnect: return code $returnCode>" if $debug;
# Print statistics
print "Completed upgrade process, printing statistics.\n";
print "\tTotal rows processed: $processedRowCount\n";
print "\tTotal rows changed: $totalCommittedRowCount\n\n";
my $oldAverage = 1;
$oldAverage = ($sumOldStringSize / $processedRowCount) if $processedRowCount > 0;
printf("\tTotal old customization string data: $sumOldStringSize bytes (average: %.2f bytes each)\n", $oldAverage) if $processedRowCount > 0;
my $newStringCount = $processedRowCount - $failedRowCount;
my $newAverage = 1;
$newAverage = ($sumNewStringSize / $newStringCount) if $newStringCount > 0;
printf("\tTotal new customization string data: $sumNewStringSize bytes (average: %.2f bytes each)\n", $newAverage) if $newStringCount > 0;
my $compressionFraction = $newAverage / $oldAverage;
printf "\tCompressed to %.2f%% of original size.\n", $compressionFraction * 100;
my $difference = $sumNewStringSize - $sumNewDataSize;
printf("\tTotal overhead for binary data escaping: $difference bytes (%.2f%% increase).\n", 100.0 * (($sumNewStringSize / $sumNewDataSize) - 1.0)) if $sumNewDataSize > 0;
}
# ======================================================================
# Program Starts Here
# ======================================================================
{
collectOptions();
if ($doUpgrade)
{
initializeCustomization($customizationIdManagerFilename);
doUpgrade();
}
}
# ======================================================================

476
tools/custView.pl Executable file
View File

@@ -0,0 +1,476 @@
# ======================================================================
#
# custView.pl
# Copyright 2003 Sony Online Entertainment, Inc.
# All Rights Reserved.
#
# ======================================================================
# Used to output customization data assignments for objects in a
# SWG database. Can view customization values for a list of object
# ids or for all object ids in the database.
# Perl modules DBI and DBD::Oracle must be installed to run this tool. See www.perl.com for info on getting these modules.
# You must have PERL5LIB (or PERLLIB) set to your mapping for //depot/swg/current/tools/perllib.
use strict;
use Customization;
use DBI;
# ======================================================================
# Globals
# ======================================================================
my $modeIsView = 0;
my $modeIsChange = 0;
my $userName = "";
my $password = "changeme";
my $databaseName = "swodb";
my $debug = 0;
my $showAll = 0;
my $useOldFormat = 0;
my $useFormatVersion = 1;
my $defaultFilename = '../dsrc/sku.0/sys.shared/compiled/game/customization/customization_id_manager.mif';
my $customizationIdManagerFilename = $defaultFilename;
my $dbHandle;
my $dumpFileName;
my $dumpFileEntryNumber = 1;
# ======================================================================
sub printHelp
{
print "Calling syntax:\n";
print "\n";
print "show help:\n";
print "\t$0 -h\n";
print "\n";
print "view human-readable customization from database:\n";
print "\t$0 -V -u <database username> [-p <database password>] [-D <database>] [-d]\n";
print "\t [-m <pathToCustomizationIdManagerMifFile>] [-f format]\n";
print "\t [-a | [objectId [objectId...]]]\n";
print "\n";
print "change customization data in the database:\n";
print "\t$0 -C -u <database username> [-p <database password>] [-D <database>] [-d]\n";
print "\t -1 <path to 1-line format dump file> [-e <entry number within dump file>] objectId\n";
print "\n";
print "Option description:\n";
print "\t-V: major operating mode: view database info.\n";
print "\t-C: major operating mode: change database entry.\n";
print "\t-u: specifies the name of the user for the Oracle database.\n";
print "\t-p: [optional] specifies the password for the user of the Oracle database. Default: changeme.\n";
print "\t-D: [optional] specifies the database to attach to. Default: swodb.\n";
print "\t-d: [optional] turn on extensive debug-level output.\n";
print "\t-m: [optional] specify path to CustomizationIdManager's mif version of initialization file.\n";
print "\t Default: $defaultFilename\n";
print "\t-a: [optional] list customization variables for all objects in the database that have any customization info.\n";
print "\t-f: [optional] customization string format: format = 1 (for new packed format version 1), old2 (for old unpacked format version 2).\n";
print "\t Default: 1.\n";
print "\t-h: [optional] print this help info.\n";
print "\t-1: filename containing 1-line dump format (one entry per line) of Oracle select dump(appearance_data) data.\n";
print "\t-e: [optional] specifies the 1-based entry count to use if the dump file has multiple lines. Default: 1.\n";
}
# ======================================================================
sub collectOptions
{
my $showHelp = 0;
my $exitCode = 0;
while (defined($ARGV[0]) && ($ARGV[0] =~ m/^-(.*)$/))
{
if ($1 eq 'u')
{
# Grab username.
if (@ARGV < 2)
{
print "-u option missing <database username> specification.\n";
$exitCode = 1;
last;
}
$userName = $ARGV[1];
print "<username: $userName>\n" if $debug;
# Skip past arg.
shift @ARGV;
}
elsif ($1 eq 'p')
{
# Grab password.
if (@ARGV < 2)
{
print "-p option missing <password> specification.\n";
$exitCode = 1;
next;
}
$password = $ARGV[1];
print "<password: $password>\n" if $debug;
# Skip past arg.
shift @ARGV;
}
elsif ($1 eq 'D')
{
# Grab database name.
if (@ARGV < 2)
{
print "-D option missing <database> specification.\n";
$exitCode = 1;
next;
}
$databaseName = $ARGV[1];
print "<database: $databaseName>\n" if $debug;
# Skip past arg.
shift @ARGV;
}
elsif ($1 eq 'C')
{
$modeIsChange = 1;
print "major mode is change\n" if $debug;
}
elsif ($1 eq 'd')
{
$debug = 1;
$Customization::Debug = 1;
}
elsif ($1 eq 'a')
{
$showAll = 1;
}
elsif ($1 eq 'h')
{
$showHelp = 1;
}
elsif ($1 eq 'm')
{
# Grab commit count.
if (@ARGV < 2)
{
print "-m option missing <CustomizationIdManager MIF file> specification.\n";
$exitCode = 1;
next;
}
$customizationIdManagerFilename = $ARGV[1];
print "<customizationIdManagerFilename: $customizationIdManagerFilename\n" if $debug;
# Skip past arg.
shift @ARGV;
}
elsif ($1 eq 'f')
{
# Grab commit count.
if (@ARGV < 2)
{
print "-f option missing <format> specification.\n";
$exitCode = 1;
next;
}
if ($ARGV[1] =~ s/^old//i)
{
$useOldFormat = 1;
}
print "<useOldFormat: $useOldFormat>\n" if $debug;
$useFormatVersion = $ARGV[1];
print "<useFormatVersion: $useFormatVersion>\n" if $debug;
# Skip past arg.
shift @ARGV;
}
elsif ($1 eq 'V')
{
$modeIsView = 1;
print "major mode is viewing\n" if $debug;
}
elsif ($1 eq '1')
{
$dumpFileName = $ARGV[1];
shift @ARGV;
print "dumpFileName=[$dumpFileName]\n" if $debug;
}
elsif ($1 eq 'e')
{
$dumpFileEntryNumber = $ARGV[1];
shift @ARGV;
print "dumpFileEntryNumber=$dumpFileEntryNumber\n" if $debug;
}
else
{
warn "unknown option [$1].";
$exitCode = 1;
}
# Process next argument.
shift @ARGV;
}
# Check for missing options.
if (!$showHelp && (length $userName < 1))
{
print "missing -u username option.\n";
$exitCode = 1;
}
# Make sure show all or command line args exist.
if (!$showHelp && (!$showAll && (@ARGV < 1)))
{
print "must specify one or more object IDs or -a option for all objects.\n";
$exitCode = 1;
}
# Show help as needed.
if ($showHelp || ($exitCode != 0))
{
printHelp();
exit($exitCode);
}
}
sub getVariableInfo(\%$)
{
my $variableInfoRef = shift;
my $customizationString = shift;
if ($useOldFormat)
{
if ($useFormatVersion == 2)
{
getVariableInfoFromOldString(%$variableInfoRef, $customizationString);
}
else
{
die "The only old version format supported is version 2, user specified [$useFormatVersion].";
}
}
else
{
if ($useFormatVersion == 1)
{
getVariableInfoFromNewString(%$variableInfoRef, $customizationString);
}
else
{
die "New version format [$useFormatVersion] unsupported.";
}
}
}
# ======================================================================
sub printView($\%)
{
my $objectId = shift;
my $variableInfoRef = shift;
print "object id: $objectId\n";
dumpVariableInfo(%$variableInfoRef);
print "\n";
}
# ======================================================================
sub handleRow(\@)
{
my $rowRef = shift;
# Validate row entry count.
die "Returned row has " . @$rowRef . "entries, expecting 2." if (@$rowRef != 2);
# Retrieve object id and old customization data.
my $objectId = $$rowRef[0];
my $customizationString = $$rowRef[1];
print "<row: id=[$objectId]: string length [" . (length $customizationString) . "]>\n" if $debug;
my %variableInfo = ();
my $success = getVariableInfo(%variableInfo, $customizationString);
die "getVariableInfo() failed for object id [$objectId]." if !$success;
printView($objectId, %variableInfo);
}
# ======================================================================
sub doView
{
if ($showAll)
{
print "<viewing: all>\n" if $debug;
# Prepare the SELECT statement: grab all non-empty appearance_data and associated object ids.
my $statementHandle = $dbHandle->prepare("SELECT object_id, appearance_data FROM tangible_objects WHERE LENGTH(appearance_data) > 0") or die $dbHandle->errstr;
$statementHandle->execute() or die $statementHandle->errstr;
while (my @row = $statementHandle->fetchrow_array)
{
handleRow(@row);
}
}
else
{
print "<viewing: [@ARGV]>\n" if $debug;
# Prepare the SELECT statement: grab all non-empty appearance_data and associated object ids.
my $statementHandle = $dbHandle->prepare("SELECT object_id, appearance_data FROM tangible_objects WHERE (LENGTH(appearance_data) > 0) AND object_id = ?") or die $dbHandle->errstr;
for (; defined($ARGV[0]); shift @ARGV)
{
$statementHandle->execute($ARGV[0]) or die $statementHandle->errstr;
my @row = $statementHandle->fetchrow_array;
if (!@row)
{
print "object id [$ARGV[0]] has no customization data.\n";
next;
}
handleRow(@row);
}
}
}
# ----------------------------------------------------------------------
sub convertOracleDumpToString
{
my $oracleDumpString = shift;
my $newString = "";
# remove header info.
$oracleDumpString =~ s/^\s*(\d+)?.*:\s*//;
my $objectId = $1;
while (length($oracleDumpString) > 0)
{
if ($oracleDumpString =~ s/^(\d+)(\s*,\s*)?//)
{
$newString .= chr($1);
}
else
{
print STDERR "convertOracleDumpToString: ", length($oracleDumpString), " characters remain: [val=", ord(substr($oracleDumpString,0,1)), "].\n";
return $newString;
}
}
return $newString;
}
# ----------------------------------------------------------------------
sub extractAppearanceDataFromFile
{
my $dumpFile;
open($dumpFile, '< ' . $dumpFileName) or die "failed to open dump file [$dumpFileName]: $!";
my $entry = 1;
while (<$dumpFile>)
{
# Check if we're dealing with the proper entry.
if ($entry == $dumpFileEntryNumber)
{
chomp;
my $appearanceData = convertOracleDumpToString($_);
close($dumpFile) or die "Failed to close dump file: $!";
return $appearanceData;
}
# Increment loop.
++$entry;
}
close($dumpFile) or die "Failed to close dump file: $!";
die "Entry [$dumpFileEntryNumber] does not exist in file [$dumpFileName] with [$entry] entries.";
}
# ----------------------------------------------------------------------
sub updateAppearanceData
{
# Retrieve args.
my $objectId = shift;
my $appearanceData = shift;
# Execute query.
my $rowCount = $dbHandle->do("UPDATE tangible_objects SET appearance_data=? WHERE object_id=$objectId", undef, $appearanceData) or die $dbHandle->errstr;
$dbHandle->commit() or die $dbHandle->errstr;
print "[$rowCount] rows updated.\n";
}
# ----------------------------------------------------------------------
sub doChange
{
# Get the line.
my $appearanceData = extractAppearanceDataFromFile();
die "Could not extract appearance data from 1-line dump file.\n" if !defined($appearanceData);
# Update the database.
die "Expecting objectId at end of line.\n" if (@ARGV != 1);
my $objectId = $ARGV[0];
updateAppearanceData($objectId, $appearanceData);
}
# ----------------------------------------------------------------------
sub connectDatabase
{
# Open the database connection.
$dbHandle = DBI->connect("dbi:Oracle:$databaseName", $userName, $password, { RaiseError => 1, AutoCommit => 0 });
error("failed to open database: [$DBI::errstr]") if !defined($dbHandle);
print "<connection: opened connection to database [$databaseName] as user [$userName] successfully.>\n" if $debug;
}
# ----------------------------------------------------------------------
sub disconnectDatabase
{
# Close the database connection.
my $returnCode = $dbHandle->disconnect or warn $dbHandle->errstr;
print "<disconnect: return code $returnCode>\n" if $debug;
}
# ======================================================================
# Program Starts Here
# ======================================================================
{
collectOptions();
connectDatabase();
if ($modeIsView)
{
Customization::initializeCustomization($customizationIdManagerFilename);
doView();
}
elsif ($modeIsChange)
{
doChange();
}
else
{
die "Major mode is neither viewing or changing.\n";
}
disconnectDatabase();
}
# ======================================================================

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More