Removed some spurious newlines that I introduced into CMakeLists.txt.

master
Logan Dethrow 2011-09-09 14:20:19 -04:00
commit 8a952e42e9
1351 changed files with 56494 additions and 64962 deletions

View File

@ -33,6 +33,7 @@ indra/newview/character
indra/newview/fmod.dll
indra/newview/mozilla-theme
indra/newview/mozilla-universal-darwin.tgz
indra/newview/res/ll_icon.*
indra/newview/res-sdl
indra/newview/vivox-runtime
indra/server-linux-*

58
.hgtags
View File

@ -122,24 +122,68 @@ dac76a711da5f1489a01c1fa62ec97d99c25736d 2.6.6-release
8f2da1701c81a62352df2b8d413d27fb2cade9a6 DRTVWR-46_2.6.3-release
8f2da1701c81a62352df2b8d413d27fb2cade9a6 2.6.3-release
77e5a08344c95738ab879f9671b7758cddd712a3 DRTVWR-56_2.6.9-release
77e5a08344c95738ab879f9671b7758cddd712a3 2.6.9-release
8835e0e3c0d3a48244c287bc05811dfc2fba43ec 2.7.0-start
43c7ee846b7eed80786acbbf35d03bd016a3e85d DRTVWR-59_2.7.0-beta1
43c7ee846b7eed80786acbbf35d03bd016a3e85d 2.7.0-beta1
77e5a08344c95738ab879f9671b7758cddd712a3 2.6.9-release
54fd44ac92e4c61435ea33effe093a3527e18d98 2.7.1-start
0c4d0c24278074f219e5a32e72b449e78301d11b DRTVWR-61_2.7.1-beta1
0c4d0c24278074f219e5a32e72b449e78301d11b 2.7.1-beta1
8f2da1701c81a62352df2b8d413d27fb2cade9a6 DRTVWR-46_2.6.3-release
8f2da1701c81a62352df2b8d413d27fb2cade9a6 2.6.3-release
77e5a08344c95738ab879f9671b7758cddd712a3 DRTVWR-56_2.6.9-release
a9abb9633a266c8d2fe62411cfd1c86d32da72bf DRTVWR-60_2.7.1-release
a9abb9633a266c8d2fe62411cfd1c86d32da72bf 2.7.1-release
9f79a6ed8fdcd2f3dac33ea6b3236eeb278dccfe 2.7.2-start
e0dc8b741eaa27dcdfbc9e956bb2579b954d15eb DRTVWR-63_2.7.2-beta1
e0dc8b741eaa27dcdfbc9e956bb2579b954d15eb 2.7.2-beta1
6a3e7e403bd19e45fdfc2fcc716867af3ab80861 2.7.3-start
6af10678de4736222b2c3f7e010e984fb5b327de 2.7.4-start
77e5a08344c95738ab879f9671b7758cddd712a3 2.6.9-release
be963a4eef635542f9617d7f5fd22ba48fb71958 DRTVWR-67_2.7.4-beta1
be963a4eef635542f9617d7f5fd22ba48fb71958 2.7.4-beta1
057f319dd8eccdf63a54d99686c68cdcb31b6abc DRTVWR-66_2.7.4-release
057f319dd8eccdf63a54d99686c68cdcb31b6abc 2.7.4-release
a9abb9633a266c8d2fe62411cfd1c86d32da72bf DRTVWR-60_2.7.1-release
be963a4eef635542f9617d7f5fd22ba48fb71958 DRTVWR-67_2.7.4-beta1
be963a4eef635542f9617d7f5fd22ba48fb71958 2.7.4-beta1
a9abb9633a266c8d2fe62411cfd1c86d32da72bf 2.7.1-release
e0dc8b741eaa27dcdfbc9e956bb2579b954d15eb DRTVWR-63_2.7.2-beta1
e0dc8b741eaa27dcdfbc9e956bb2579b954d15eb 2.7.2-beta1
19a498fa62570f352d7d246f17e3c81cc1d82d8b 2.7.5-start
09984bfa6cae17e0f72d02b75c1b7393c65eecfc DRTVWR-69_2.7.5-beta1
09984bfa6cae17e0f72d02b75c1b7393c65eecfc 2.7.5-beta1
e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-start
502f6a5deca9365ddae57db4f1e30172668e171e 2.8.1-start
6866d9df6efbd441c66451debd376d21211de39c DRTVWR-68_2.7.5-release
6866d9df6efbd441c66451debd376d21211de39c 2.7.5-release
e1ed60913230dd64269a7f7fc52cbc6004f6d52c DRTVWR-71_2.8.0-beta1
e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-beta1
493d9127ee50e84ba08a736a65a23ca86f7a5b01 DRTVWR-70_2.8.0-release
493d9127ee50e84ba08a736a65a23ca86f7a5b01 2.8.0-release
2c7e459e0c883f8e406b932e41e60097e9ee077e DRTVWR-73_2.8.1-beta1
2c7e459e0c883f8e406b932e41e60097e9ee077e 2.8.1-beta1
29e93d7e19991011bd12b5748142b11a5dcb4370 DRTVWR-72_2.8.1-release
29e93d7e19991011bd12b5748142b11a5dcb4370 2.8.1-release
4780e3bd2b3042f91be3426151f28c30d199bb3b DRTVWR-76_2.8.1-hotfix
4780e3bd2b3042f91be3426151f28c30d199bb3b 2.8.1-hotfix
54bc7823ad4e3a436fef79710f685a7372bbf795 2.8.2-start
29e93d7e19991011bd12b5748142b11a5dcb4370 DRTVWR-72_2.8.1-release
29e93d7e19991011bd12b5748142b11a5dcb4370 2.8.1-release
ac0f1a132d35c02a58861d37cca75b0429ac9137 2.8.3-start
599677276b227357140dda35bea4a2c18e2e67b5 DRTVWR-75_2.8.3-beta1
599677276b227357140dda35bea4a2c18e2e67b5 2.8.3-beta1
fb85792b84bf28428889c4cc966469d92e5dac4c DRTVWR-74_2.8.3-release
fb85792b84bf28428889c4cc966469d92e5dac4c 2.8.3-release
46a010f4885a9d223b511eac553ba5720284b1dc 3.0.0-start
b0be6ce3adfef3a014a2389d360539f8a86c5439 DRTVWR-78_3.0.0-beta1
b0be6ce3adfef3a014a2389d360539f8a86c5439 3.0.0-beta1
6b678ea52f90d5c14181661dcd2546e25bde483e 3.0.0-start
82a2079ffcb57ecb1b3849cb41376b443e1eb912 3.0.1-start
364fd63517fbacbbcb9129d096187171ba8c9e48 DRTVWR-81_3.0.1-beta1
364fd63517fbacbbcb9129d096187171ba8c9e48 3.0.1-beta1
f2412ecd6740803ea9452f1d17fd872e263a0df7 3.0.2-start
1778f26b6d0ae762dec3ca37140f66620f2485d9 DRTVWR-78_3.0.0-release
1778f26b6d0ae762dec3ca37140f66620f2485d9 3.0.0-release
42784bf50fa01974bada2a1af3892ee09c93fcda DRTVWR-83_3.0.2-beta1
42784bf50fa01974bada2a1af3892ee09c93fcda 3.0.2-beta1
e5c9af2d7980a99a71650be3a0cf7b2b3c3b897e DRTVWR-86_3.0.2-beta2
e5c9af2d7980a99a71650be3a0cf7b2b3c3b897e 3.0.2-beta2
b95ddac176ac944efdc85cbee94ac2e1eab44c79 3.0.3-start
6694f3f062aa45f64ab391d25a3eb3d5eb1b0871 DRTVWR-85_3.0.3-beta1
586907287be581817b2422b5137971b22d54ea48 3.0.4-start
6694f3f062aa45f64ab391d25a3eb3d5eb1b0871 3.0.3-beta1

43
BuildParams Normal file → Executable file
View File

@ -14,8 +14,8 @@ public_build = true
# skip windows debug build until we can get a fix in.
build_CYGWIN_Debug = false
# Update Public Inworld Build Status Indicators
email_status_this_is_os = false
# Update Public Inworld Build Status Indicators (setting should mirror "public_build")
email_status_this_is_os = true
# Limit extent of codeticket updates to revisions after...
codeticket_since = 2.2.0-release
@ -42,6 +42,12 @@ snowstorm_viewer-development.viewer_channel = "Second Life Development"
snowstorm_viewer-development.login_channel = "Second Life Development"
snowstorm_viewer-development.build_viewer_update_version_manager = false
snowstorm_viewer-development.email = viewer-development-builds@lists.secondlife.com
snowstorm_viewer-development.build_enforce_coding_policy = true
Snowstorm_viewer-project-review.build_debug_release_separately = true
Snowstorm_viewer-project-review.codeticket_add_context = true
Snowstorm_viewer-project-review.viewer_channel = "Project Viewer - Snowstorm Team"
Snowstorm_viewer-project-review.login_channel = "Project Viewer - Snowstorm Team"
# ========================================
# Viewer Beta
@ -82,6 +88,26 @@ mesh-development.build_debug_release_separately = true
mesh-development.build_CYGWIN_Debug = false
mesh-development.build_viewer_update_version_manager = false
# ========================================
# mesh-development-release-1-candidate
# ========================================
mesh-development-release-1-candidate.viewer_channel = "Project Viewer - Mesh"
mesh-development-release-1-candidate.login_channel = "Project Viewer - Mesh"
mesh-development-release-1-candidate.viewer_grid = agni
mesh-development-release-1-candidate.build_debug_release_separately = true
mesh-development-release-1-candidate.build_CYGWIN_Debug = false
mesh-development-release-1-candidate.build_viewer_update_version_manager = false
# ========================================
# mesh-development-rc
# ========================================
mesh-development-rc.viewer_channel = "Project Viewer - Mesh"
mesh-development-rc.login_channel = "Project Viewer - Mesh"
mesh-development-rc.viewer_grid = agni
mesh-development-rc.build_debug_release_separately = true
mesh-development-rc.build_CYGWIN_Debug = false
mesh-development-rc.build_viewer_update_version_manager = false
# ========================================
# mesh-asset-deprecation
# ========================================
@ -122,6 +148,7 @@ cg_viewer-development_lenny.email = cg@lindenlab.com
oz_viewer-devreview.build_debug_release_separately = true
oz_viewer-devreview.codeticket_add_context = false
oz_viewer-devreview.build_enforce_coding_policy = true
oz_project-1.build_debug_release_separately = true
oz_project-1.codeticket_add_context = false
@ -134,9 +161,8 @@ oz_project-4.codeticket_add_context = false
oz_viewer-beta-review.build_debug_release_separately = true
oz_viewer-beta-review.codeticket_add_context = false
oz_viewer-poreview.build_debug_release_separately = true
oz_viewer-poreview.codeticket_add_context = false
oz_viewer-beta-review.viewer_channel = "Second Life Beta Viewer"
oz_viewer-beta-review.login_channel = "Second Life Beta Viewer"
# =================================================================
# asset delivery 2010 projects
@ -155,4 +181,11 @@ viewer-asset-delivery-metrics.email = monty@lindenlab.com
viewer-asset-delivery-metrics.build_server = false
viewer-asset-delivery-metrics.build_server_tests = false
# ========================================
# Simon says
# ========================================
simon_viewer-dev-private.public_build = false
simon_viewer-dev-private.email_status_this_is_os = false
# eof

View File

@ -246,9 +246,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>d05be8fc196e9ce7b6636b931cf13dff</string>
<string>be7321370b69b6d66938b82a9230a067</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-colladadom/rev/226716/arch/Linux/installer/colladadom-2.2-linux-20110415.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-colladadom/rev/233450/arch/Linux/installer/colladadom-2.2-linux-20110621.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
@ -1110,9 +1110,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>6e45ad68506cd1ba49fd35a3201f0478</string>
<string>362654a472ef7368d4c803ae3fb89d95</string>
<key>url</key>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/228821/arch/Darwin/installer/llconvexdecomposition-0.1-darwin-20110504.tar.bz2</string>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/238959/arch/Darwin/installer/llconvexdecomposition-0.1-darwin-20110819.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
@ -1122,9 +1122,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>00ff5144612c2e261a0811a4503ce3ba</string>
<string>c7801d899daec5338fbe95053255b7e7</string>
<key>url</key>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/228821/arch/Linux/installer/llconvexdecomposition-0.1-linux-20110504.tar.bz2</string>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/238959/arch/Linux/installer/llconvexdecomposition-0.1-linux-20110819.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
@ -1134,9 +1134,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>a4635dcbbe0915ce023dd41d3b848d4c</string>
<string>6ecf2f85f03c5ae87fe45769566a5660</string>
<key>url</key>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/228821/arch/CYGWIN/installer/llconvexdecomposition-0.1-windows-20110504.tar.bz2</string>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/238959/arch/CYGWIN/installer/llconvexdecomposition-0.1-windows-20110819.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -1148,7 +1148,7 @@
<key>license</key>
<string>lgpl</string>
<key>license_file</key>
<string>LICENSES/lgpl.txt</string>
<string>LICENSES/LLConvexDecompositionStubLicense.txt</string>
<key>name</key>
<string>llconvexdecompositionstub</string>
<key>platforms</key>
@ -1158,9 +1158,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>bc1388fc28dbb3bba1fe7cb8d09f49b4</string>
<string>a5f53e09f67271fd50f1131ffdda9d27</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llconvexdecompositionstub/rev/227399/arch/Darwin/installer/llconvexdecompositionstub-0.3-darwin-20110421.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llconvexdecompositionstub/rev/238958/arch/Darwin/installer/llconvexdecompositionstub-0.3-darwin-20110819.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
@ -1170,9 +1170,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>3295bd4a0514b7c15dda9044f40c175e</string>
<string>0006a964f1497f55a5f181b7042d2d22</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llconvexdecompositionstub/rev/227399/arch/Linux/installer/llconvexdecompositionstub-0.3-linux-20110422.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llconvexdecompositionstub/rev/238958/arch/Linux/installer/llconvexdecompositionstub-0.3-linux-20110819.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
@ -1182,9 +1182,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>92f1dff3249024c1534b55343ed79ea3</string>
<string>b859e7e3bb03ebb467f0309f46422995</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llconvexdecompositionstub/rev/227399/arch/CYGWIN/installer/llconvexdecompositionstub-0.3-windows-20110421.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llconvexdecompositionstub/rev/238958/arch/CYGWIN/installer/llconvexdecompositionstub-0.3-windows-20110819.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -1206,9 +1206,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>82798d0da3ac3d97c91517a575d9ea1c</string>
<string>9cd66e879908f047d9af665b92946ecc</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/231093/arch/Darwin/installer/llqtwebkit-4.7.1-darwin-20110526.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/239803/arch/Darwin/installer/llqtwebkit-4.7.1-darwin-20110830.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
@ -1230,9 +1230,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>f0708d18943a05013493f69ab7dc6429</string>
<string>ab9393795515cbbe9526bde33b41bf2a</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/231093/arch/CYGWIN/installer/llqtwebkit-4.7.1-windows-20110526.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/239670/arch/CYGWIN/installer/llqtwebkit-4.7.1-windows-20110829.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -1570,9 +1570,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>e19576af3c0affc71293d8f0bcce2606</string>
<string>24e735ae005f3ce7a21a09cc02cece17</string>
<key>url</key>
<string> http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/slvoice-3.2.0002.9361-darwin-20110120.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-slvoice/rev/231678/arch/Darwin/installer/slvoice-3.2.0002.10426-darwin-20110601.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
@ -1582,9 +1582,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>53fefed8120d7c6a0eb6778edae6fa32</string>
<string>8a0bc982367d6fdc20a28b391cd40566</string>
<key>url</key>
<string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/slvoice-3.2.0002.9361-linux-20110120.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-slvoice/rev/231678/arch/Linux/installer/slvoice-3.2.0002.10426-linux-20110601.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
@ -1594,9 +1594,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>44f84b3b45f7067a104a7c34d50d62f0</string>
<string>1e821cc7d25eabad013b7f3db260dd6b</string>
<key>url</key>
<string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/slvoice-3.2.0002.9361-windows-20110120.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-slvoice/rev/231678/arch/CYGWIN/installer/slvoice-3.2.0002.10426-windows-20110601.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -1907,15 +1907,12 @@
<map>
<key>build</key>
<map>
<key>arguments</key>
<array>
<string>|</string>
<string>grep</string>
<string>-v</string>
<string>setenv</string>
</array>
<key>command</key>
<string>xcodebuild</string>
<key>filters</key>
<array>
<string>setenv</string>
</array>
<key>options</key>
<array>
<string>-configuration Debug</string>
@ -1964,15 +1961,12 @@
<map>
<key>build</key>
<map>
<key>arguments</key>
<array>
<string>|</string>
<string>grep</string>
<string>-v</string>
<string>setenv</string>
</array>
<key>command</key>
<string>xcodebuild</string>
<key>filters</key>
<array>
<string>setenv</string>
</array>
<key>options</key>
<array>
<string>-configuration RelWithDebInfo</string>
@ -2023,15 +2017,12 @@
<map>
<key>build</key>
<map>
<key>arguments</key>
<array>
<string>|</string>
<string>grep</string>
<string>-v</string>
<string>setenv</string>
</array>
<key>command</key>
<string>xcodebuild</string>
<key>filters</key>
<array>
<string>setenv</string>
</array>
<key>options</key>
<array>
<string>-configuration Release</string>

View File

@ -209,7 +209,7 @@ do
end_section BuildParallel
else
begin_section "Build$variant"
build "$variant" "$build_dir" 2>&1 | tee -a "$build_log" | grep --line-buffered "^##teamcity"
build "$variant" "$build_dir" 2>&1 | tee -a "$build_log" | sed -n 's/^ *\(##teamcity.*\)/\1/p'
if `cat "$build_dir/build_ok"`
then
echo so far so good.
@ -238,7 +238,7 @@ then
begin_section "Build$variant"
build_dir=`build_dir_$arch $variant`
build_dir_stubs="$build_dir/win_setup/$variant"
tee -a $build_log < "$build_dir/build.log" | grep --line-buffered "^##teamcity"
tee -a $build_log < "$build_dir/build.log" | sed -n 's/^ *\(##teamcity.*\)/\1/p'
if `cat "$build_dir/build_ok"`
then
echo so far so good.

View File

@ -1,8 +1,8 @@
Linden Lab would like to acknowledge source code contributions from the
Linden Lab would like to acknowledge contributions from the
following residents. The Second Life resident name is given below,
along with the issue identifier corresponding to the patches we've
received from them.
along with the issue identifiers to which they have contributed.
45ms Zhong
Able Whitman
VWR-650
VWR-1460
@ -11,15 +11,20 @@ Able Whitman
VWR-1813
Adam Marker
VWR-2755
Adeon Writer
Aeonix Aeon
Agathos Frascati
CT-246
CT-317
CT-352
Ai Austin
Aiko Ying
Aimee Trescothick
SNOW-227
SNOW-570
SNOW-572
SNOW-575
STORM-1315
VWR-3321
VWR-3336
VWR-3903
@ -60,11 +65,15 @@ Aimee Trescothick
Alejandro Rosenthal
VWR-1184
Aleric Inglewood
SNOW-84
SNOW-240
SNOW-477
SNOW-522
SNOW-626
SNOW-744
SNOW-756
SNOW-764
SNOW-766
SNOW-800
VWR-10001
VWR-10579
@ -90,11 +99,8 @@ Aleric Inglewood
VWR-24366
VWR-24519
VWR-24520
SNOW-84
SNOW-477
SNOW-744
SNOW-766
STORM-163
STORM-864
STORM-955
STORM-960
Ales Beaumont
@ -103,6 +109,7 @@ Ales Beaumont
Alexandrea Fride
STORM-255
STORM-960
STORM-1459
Alissa Sabre
VWR-81
VWR-83
@ -152,12 +159,18 @@ Alissa Sabre
VWR-12620
VWR-12789
SNOW-322
Alliez Mysterio
Angus Boyd
VWR-592
Ann Congrejo
CT-193
Annie Milestone
Annika Genezzia
Ansariel Hiller
STORM-1101
VWR-25480
VWR-26150
Aralara Rajal
Ardy Lay
STORM-859
VWR-19499
@ -166,16 +179,30 @@ Argent Stonecutter
VWR-68
Armin Weatherwax
VWR-8436
ArminasX Saiman
Arya Braveheart
Asaeda Meltingdots
Asturkon Jua
Asuka Neely
VWR-3434
VWR-8179
Aura Dirval
Avallyn Oakleaf
Avatar Quinzet
BabyA Littlething
Bacchus Ireto
Balp Allen
VWR-4157
Bazaar
Be Holder
SNOW-322
SNOW-397
Beansy Twine
Benja Kepler
VWR-746
Benjamin Bigdipper
Beth Walcher
Bezilon Kasei
Biancaluce Robbiani
CT-225
CT-226
@ -186,6 +213,7 @@ Biancaluce Robbiani
CT-231
CT-321
CT-352
Bill Walach
Blakar Ogre
VWR-418
VWR-881
@ -195,10 +223,13 @@ Blakar Ogre
VWR-2164
blino Nakamura
VWR-17
Blitzckreed Levenque
Borg Capalini
Boroondas Gupte
OPEN-29
OPEN-39
OPEN-39
OPEN-99
SNOW-278
SNOW-503
SNOW-510
@ -214,7 +245,11 @@ Boroondas Gupte
VWR-20891
VWR-23455
VWR-24487
VWR-26066
VWR-26458
WEB-262
Bryn Oh
Buckaroo Mu
Bulli Schumann
CT-218
CT-219
@ -229,6 +264,9 @@ Bulli Schumann
bushing Spatula
VWR-119
VWR-424
blakopal Galicia
Callipygian Christensen
Cap Carver
Carjay McGinnis
VWR-3737
VWR-4070
@ -236,37 +274,64 @@ Carjay McGinnis
VWR-6154
VWR-9400
VWR-9620
Carla Broek
Carr Arbenlow
Catherine Pfeffer
VWR-1282
VWR-8624
VWR-10854
Cayu Cluny
Celierra Darling
VWR-1274
VWR-6975
Chantal Harvey
Charles Courtois
Charlie Sazaland
Cherry Cheevers
ChickyBabes Zuzu
Christopher Organiser
Ciaran Laval
Clara Young
Coaldust Numbers
VWR-1095
Colpo Wexler
Corinne Helendale
Corro Moseley
Coughdrop Littlething
Cron Stardust
VWR-10579
VWR-25120
STORM-1075
Cypren Christenson
STORM-417
Dante Tucker
Dale Glass
VWR-120
VWR-560
VWR-2502
VWR-1358
VWR-2041
Darien Caldwell
Dartagan Shepherd
Debs Regent
Decro Schmooz
Denim Kamachi
DiJodi Dubratt
Dil Spitz
Dimitrio Lewis
Dirk
Draconis Neurocam
STORM-1259
Drew Dri
VWR-19683
Drew Dwi
Drewan Keats
VWR-28
VWR-248
VWR-412
VWR-638
VWR-660
Dusan Writer
Dylan Haskell
VWR-72
Dzonatas Sol
@ -289,28 +354,51 @@ Eddy Stryker
VWR-23
VWR-1468
VWR-1475
Edgware Marker
Egehan Dryke
Ellla McMahon
Elric Anatine
Emma Portilo
Emmie Fairymeadow
EponymousDylan Ra
VWR-1289
VWR-1465
Eva Nowicka
CT-324
CT-352
Eva Rau
Evangelista Emerald
Faelon Swordthain
Farallon Greyskin
VWR-2036
Feep Larsson
VWR-447
VWR-1314
VWR-4444
Fiachra Lach
Flemming Congrejo
CT-193
CT-318
Flower Ducatillon
Fluf Fredriksson
VWR-3450
Fremont Cunningham
VWR-1147
FreeSL Aeon
Frenchimmo Sabra
Frontera Thor
Fury Rosewood
Gaberoonie Zanzibar
Ganymedes Costagravas
Gene Frostbite
GeneJ Composer
Geneko Nemeth
CT-117
VWR-11069
Gentle Heron
Gentle Welinder
gwampa Lomu
Giggles Littlebird
Gigs Taggart
SVC-493
VWR-6
@ -336,20 +424,31 @@ Gigs Taggart
VWR-8783
Ginko Bayliss
VWR-4
Grady Echegaray
Grazer Kline
VWR-1092
VWR-2113
Gudmund Shepherd
VWR-1594
VWR-1873
Guni Greenstein
Gwyneth Llewelyn
Gypsy Tripsa
Hackshaven Harford
Ham Rambler
Hamncheese Omlet
VWR-333
Han Shuffle
Hanglow Short
HappySmurf Papp
CT-193
Harleen Gretzky
Hatzfeld Runo
Henri Beauchamp
VWR-1320
VWR-1406
VWR-4157
herina Bode
Hikkoshi Sakai
VWR-429
Hiro Sommambulist
@ -362,23 +461,34 @@ Hiro Sommambulist
VWR-132
VWR-136
VWR-143
Holger Gilruth
Horatio Freund
Hoze Menges
VWR-255
Hydra Shaftoe
Hypatia Callisto
Hypatia Pickens
Ian Kas
VWR-8780 (Russian localization)
[NO JIRA] (Ukranian localization)
CT-322
CT-325
Identity Euler
Ima Mechanique
OPEN-50
OPEN-61
OPEN-76
STORM-1175
Imnotgoing Sideways
Inma Rau
Innula Zenovka
Irene Muni
CT-324
CT-352
Iskar Ariantho
VWR-1223
VWR-11759
Iyoba Tarantal
Jacek Antonelli
SNOW-388
VWR-165
@ -392,9 +502,18 @@ Jacek Antonelli
VWR-2948
VWR-3605
VWR-8617
Jack Abraham
Jagga Meredith
JB Kraft
VWR-5283
VWR-7802
Jennifer Boyle
Jeremy Marquez
Jessica Qin
Jinx Nordberg
Jo Bernandes
Jocial Sonnenkern
Joel Savard
Joghert LeSabre
VWR-64
Jonathan Yap
@ -446,17 +565,40 @@ Jonathan Yap
STORM-1313
STORM-899
STORM-1273
STORM-1276
STORM-1462
STORM-1459
STORM-1522
STORM-1567
STORM-1572
STORM-1574
Kadah Coba
STORM-1060
Jondan Lundquist
Josef Munster
Josette Windlow
Juilan Tripsa
Juro Kothari
Justin RiversRunRed
Kage Pixel
VWR-11
Kagehi Kohn
Kaimen Takahe
Keklily Longfall
Ken Lavender
Ken March
CT-245
Kestral Karas
Kerutsen Sellery
VWR-1350
Khisme Nitely
Khyota Wulluf
VWR-2085
VWR-8885
VWR-9256
VWR-9966
Kimar Coba
Kithrak Kirkorian
Kitty Barnett
VWR-19699
STORM-288
@ -465,6 +607,9 @@ Kitty Barnett
STORM-1001
STORM-1175
VWR-24217
Kolor Fall
Komiko Okamoto
Korvel Noh
Kunnis Basiat
VWR-82
VWR-102
@ -474,6 +619,7 @@ Latif Khalifa
VWR-5370
leliel Mirihi
STORM-1100
len Starship
Lisa Lowe
CT-218
CT-219
@ -485,16 +631,40 @@ Lisa Lowe
CT-319
Lockhart Cordoso
VWR-108
LSL Scientist
Lamorna Proctor
Lares Carter
Larry Pixel
Laurent Bechir
Leal Choche
Lenae Munz
Lexi Frua
Lillie Cordeaux
Lilly Zenovka
Lizzy Macarthur
Luban Yiyuan
Luc Starsider
Lunita Savira
Maccus McCullough
maciek marksman
CT-86
Madison Blanc
Maggie Darwin
Magnus Balczo
CT-138
Malarthi Behemoth
Mallory Destiny
Malwina Dollinger
CT-138
Manx Wharton
march Korda
SVC-1020
Marc Claridge
Marc2 Sands
Marianne McCann
Marine Kelley
STORM-281
Matthew Anthony
Matthew Dowd
VWR-1344
VWR-1651
@ -502,6 +672,8 @@ Matthew Dowd
VWR-1737
VWR-1761
VWR-2681
Matto Destiny
Maxim RiversRunRed
McCabe Maxsted
SNOW-387
VWR-1318
@ -515,6 +687,10 @@ McCabe Maxsted
VWR-8454
VWR-8689
VWR-9007
Medhue Simoni
Mel Vanbeeck
Melinda Latynina
Mencius Watts
Michelle2 Zenovka
STORM-477
VWR-2652
@ -532,6 +708,13 @@ Michelle2 Zenovka
VWR-8889
VWR-8310
VWR-9499
STORM-1060
Michi Lumin
Midian Farspire
Miles Glaz
Mindy Mathy
Minerva Memel
Mitch Wagner
Mm Alder
SNOW-376
VWR-197
@ -539,8 +722,20 @@ Mm Alder
VWR-4232
VWR-4794
VWR-13578
Mo Hax
Mourna Biziou
Mr Greggan
VWR-445
Nao Noe
naofan Teardrop
Naomah Beaumont
Nathiel Siamendes
Nber Medici
Neko Link
Netpat Igaly
Neutron Chesnokov
Newfie Pendragon
Nicholai Laviscu
Nicholaz Beresford
VWR-132
VWR-176
@ -611,12 +806,19 @@ Nicholaz Beresford
VWR-2412
VWR-2682
VWR-2684
Nick Rhodes
Nicky Perian
OPEN-1
STORM-1087
STORM-1090
Nicoladie Gymnast
Nounouch Hapmouche
VWR-238
Ollie Kubrick
Orenj Marat
Orion Delphis
Oryx Tempel
Parvati Silverweb
Patric Mills
VWR-2645
Paul Churchill
@ -639,6 +841,9 @@ Peekay Semyorka
VWR-79
Peter Lameth
VWR-7331
PeterPunk Mooney
Pixel Gausman
Pixel Scientist
Pf Shan
CT-225
CT-226
@ -649,15 +854,29 @@ Pf Shan
CT-231
CT-321
SNOW-422
Polo Gufler
Pounce Teazle
princess niven
VWR-5733
CT-85
CT-320
CT-352
Professor Noarlunga
Psi Merlin
Quantum Destiny
Questar Utu
Quicksilver Hermes
RAT Quan
Radio Signals
Ralf Setsuko
RedMokum Bravin
Renault Clio
VWR-1976
resu Ampan
SNOW-93
Revolution Perenti
Rezit Sideways
Rich Grainger
Ringo Tuxing
CT-225
CT-226
@ -667,6 +886,7 @@ Ringo Tuxing
CT-230
CT-231
CT-321
Riva
Robin Cornelius
SNOW-108
SNOW-204
@ -687,6 +907,7 @@ Robin Cornelius
STORM-1019
STORM-1095
STORM-1128
STORM-1459
VWR-2488
VWR-9557
VWR-10579
@ -697,9 +918,17 @@ Robin Cornelius
VWR-12763
VWR-12995
VWR-20911
Rosco Teardrop
Rose Evans
Rudee Voom
RufusTT Horsefly
Ryozu Kojima
VWR-53
VWR-287
Sachi Vixen
Sahkolihaa Contepomi
Saii Hallard
SaintLEOlions Zimer
Salahzar Stenvaag
CT-225
CT-226
@ -709,11 +938,16 @@ Salahzar Stenvaag
CT-230
CT-231
CT-321
Samm Larkham
Sammy Frederix
VWR-6186
Sasy Scarborough
Satanello Miami
Satomi Ahn
STORM-501
STORM-229
VWR-24502
Scrim Pinion
Scrippy Scofield
VWR-3748
Seg Baphomet
@ -733,11 +967,16 @@ Sergen Davies
CT-230
CT-231
CT-321
SexySteven Morrisey
Shawn Kaufmat
SNOW-240
Sheet Spotter
Shnurui Troughton
Siana Gearz
STORM-960
STORM-1088
sicarius Thorne
Sicarius Toxx
SignpostMarv Martin
VWR-153
VWR-154
@ -747,6 +986,10 @@ SignpostMarv Martin
VWR-8357
Simon Nolan
VWR-409
Sini Nubalo
Sitearm Madonna
SLB Wirefly
snowy Sidran
SpacedOut Frye
VWR-34
VWR-45
@ -759,8 +1002,13 @@ SpacedOut Frye
VWR-1823
Sporked Friis
VWR-4903
Soupa Segura
Squirrel Wood
ST Mensing
Starshine Halasy
Stevex Janus
VWR-1182
Stickman Ingmann
Still Defiant
VWR-207
VWR-227
@ -776,8 +1024,13 @@ Strife Onizuka
VWR-2265
VWR-4111
SNOW-691
Sudane Erato
Synystyr Texan
Takeda Terrawyng
TankMaster Finesmith
STORM-1100
Talamasca
Tali Rosca
Tayra Dagostino
SNOW-517
SNOW-543
@ -808,8 +1061,10 @@ Techwolf Lupindo
SNOW-746
VWR-12385
VWR-20893
Templar Merlin
tenebrous pau
VWR-247
Tezcatlipoca Bisiani
Tharax Ferraris
VWR-605
Thickbrick Sleaford
@ -828,19 +1083,27 @@ Thickbrick Sleaford
VWR-24420
STORM-956
STORM-1147
STORM-1325
Thraxis Epsilon
SVC-371
VWR-383
Tiel Stonecutter
tiamat bingyi
CT-246
Tofu Buzzard
CTS-411
STORM-546
VWR-24509
Tony Kembia
Torben Trautman
TouchaHoney Perhaps
TraductoresAnonimos Alter
CT-324
Trey Reanimator
TriloByte Zanzibar
STORM-1100
Trinity Dechou
Trinity Dejavu
Tue Torok
CT-68
CT-69
@ -856,13 +1119,26 @@ Twisted Laws
STORM-643
STORM-954
STORM-1103
Unlikely Quintessa
UsikuFarasi Kanarik
Vadim Bigbear
VWR-2681
Vector Hastings
VWR-8726
Veritas Raymaker
Vex Streeter
Viaticus Speculaas
Vick Forcella
Villain Baroque
Vixen Heron
VWR-2710
CT-88
Vixie Durant
Void Singer
Watty Berkson
Westley Schridde
Westley Streeter
Whimsy Winx
Whoops Babii
VWR-631
VWR-1640
@ -888,6 +1164,7 @@ Whoops Babii
VWR-8296
VWR-8297
VWR-8298
Winter Ventura
Wilton Lundquist
VWR-7682
WolfPup Lowenhar
@ -912,18 +1189,34 @@ WolfPup Lowenhar
STORM-1098
VWR-20741
VWR-20933
Wundur Primbee
Xiki Luik
xstorm Radek
YongYong Francois
Zak Westminster
Zai Lynch
VWR-19505
Zana Kohime
Zaren Alexander
Zarkonnen Decosta
VWR-253
Zeja Pyle
ZenMondo Wormser
Zi Ree
SH-489
VWR-423
VWR-671
VWR-682
VWR-684
VWR-9127
VWR-1140
VWR-24017
VWR-25588
Zipherius Turas
VWR-76
VWR-77
Zoex Flanagan

29
doc/translations.txt Normal file
View File

@ -0,0 +1,29 @@
#List of translators who contribute to SL Viewer 2.0+ by language
Danish
Flemming Congrejo
German
Torben Trautman
French
Valerie Linden
Polish
Identity Euler
Portuguese
Zaza Linden
Spanish
Aralara Rajal
Aura Dirval
Cayu Cluny
Eva Rau
FreeSL Aeon
Frontera Thor
Inma Rau
Irene Muni
Lunita Savira
Minerva Memel
Polo Gufler
Xiki Luik
Shinya Tandino
Catwise Yoshikawa
Traditional Chinese
gefeit Dufaux

View File

@ -1,4 +1,3 @@
# -*- cmake -*-
# cmake_minimum_required should appear before any
@ -62,7 +61,6 @@ if (WINDOWS AND EXISTS ${LIBS_CLOSED_DIR}copy_win_scripts)
add_subdirectory(${LIBS_CLOSED_PREFIX}copy_win_scripts)
endif (WINDOWS AND EXISTS ${LIBS_CLOSED_DIR}copy_win_scripts)
add_custom_target(viewer)
if (VIEWER)
add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger)

View File

@ -171,7 +171,10 @@ if (LINUX)
add_definitions(-fvisibility=hidden)
# don't catch SIGCHLD in our base application class for the viewer - some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The viewer doesn't need to catch SIGCHLD anyway.
add_definitions(-DLL_IGNORE_SIGCHLD)
add_definitions(-march=pentium4 -mfpmath=sse)
if (WORD_SIZE EQUAL 32)
add_definitions(-march=pentium4)
endif (WORD_SIZE EQUAL 32)
add_definitions(-mfpmath=sse)
#add_definitions(-ftree-vectorize) # THIS CRASHES GCC 3.1-3.2
if (NOT STANDALONE)
# this stops us requiring a really recent glibc at runtime

View File

@ -40,7 +40,7 @@ if(WINDOWS)
ssleay32.dll
libeay32.dll
libcollada14dom22-d.dll
glod.dll
glod.dll
)
set(release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
@ -71,7 +71,7 @@ if(WINDOWS)
if (MSVC80)
FIND_PATH(debug_msvc8_redist_path msvcr80d.dll
PATHS
${MSVC_DEBUG_REDIST_PATH}
${MSVC_DEBUG_REDIST_PATH}
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0\\Setup\\VC;ProductDir]/redist/Debug_NonRedist/x86/Microsoft.VC80.DebugCRT
NO_DEFAULT_PATH
NO_DEFAULT_PATH
@ -96,7 +96,7 @@ if (MSVC80)
FIND_PATH(release_msvc8_redist_path msvcr80.dll
PATHS
${MSVC_REDIST_PATH}
${MSVC_REDIST_PATH}
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0\\Setup\\VC;ProductDir]/redist/x86/Microsoft.VC80.CRT
NO_DEFAULT_PATH
NO_DEFAULT_PATH
@ -212,11 +212,11 @@ elseif(DARWIN)
libexpat.1.5.2.dylib
libexpat.dylib
libGLOD.dylib
libllqtwebkit.dylib
libminizip.a
libllqtwebkit.dylib
libminizip.a
libndofdev.dylib
libexception_handler.dylib
libcollada14dom.dylib
libcollada14dom.dylib
)
# fmod is statically linked on darwin
@ -252,19 +252,19 @@ elseif(LINUX)
libaprutil-1.so.0
libatk-1.0.so
libbreakpad_client.so.0
libcollada14dom.so
libcollada14dom.so
libcrypto.so.1.0.0
libdb-5.1.so
libexpat.so
libexpat.so.1
libglod.so
libglod.so
libgmock_main.so
libgmock.so.0
libgmodule-2.0.so
libgobject-2.0.so
libgtest_main.so
libgtest.so.0
libminizip.so
libminizip.so
libopenal.so
libopenjpeg.so
libssl.so

View File

@ -16,15 +16,15 @@ if (FMOD)
include(FindFMOD)
else (STANDALONE)
if (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
# If the path have been specified in the arguments, use that
# If the path have been specified in the arguments, use that
set(FMOD_LIBRARIES ${FMOD_LIBRARY})
MESSAGE(STATUS "Using FMOD path: ${FMOD_LIBRARIES}, ${FMOD_INCLUDE_DIR}")
MESSAGE(STATUS "Using FMOD path: ${FMOD_LIBRARIES}, ${FMOD_INCLUDE_DIR}")
else (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
# If not, we're going to try to get the package listed in autobuild.xml
# Note: if you're not using INSTALL_PROPRIETARY, the package URL should be local (file:/// URL)
# as accessing the private LL location will fail if you don't have the credential
include(Prebuilt)
use_prebuilt_binary(fmod)
# If not, we're going to try to get the package listed in autobuild.xml
# Note: if you're not using INSTALL_PROPRIETARY, the package URL should be local (file:/// URL)
# as accessing the private LL location will fail if you don't have the credential
include(Prebuilt)
use_prebuilt_binary(fmod)
if (WINDOWS)
set(FMOD_LIBRARY fmod)
elseif (DARWIN)

View File

@ -21,10 +21,10 @@ IF (NOT AUTOBUILD_EXECUTABLE)
AUTOBUILD_EXECUTABLE
NAMES ${AUTOBUILD_EXE_NAMES}
PATHS
ENV PATH
${CMAKE_SOURCE_DIR}/..
${CMAKE_SOURCE_DIR}/../..
${CMAKE_SOURCE_DIR}/../../..
ENV PATH
${CMAKE_SOURCE_DIR}/..
${CMAKE_SOURCE_DIR}/../..
${CMAKE_SOURCE_DIR}/../../..
PATH_SUFFIXES "/autobuild/bin/"
)
@ -33,7 +33,7 @@ IF (NOT AUTOBUILD_EXECUTABLE)
MESSAGE(STATUS "Using autobuild at: ${AUTOBUILD_EXECUTABLE}")
ELSE (AUTOBUILD_EXECUTABLE)
IF (AUTOBUILD_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find autobuild executable")
MESSAGE(FATAL_ERROR "Could not find autobuild executable")
ENDIF (AUTOBUILD_FIND_REQUIRED)
ENDIF (AUTOBUILD_EXECUTABLE)

View File

@ -24,8 +24,8 @@ EXEC_PROGRAM(${CMAKE_CXX_COMPILER}
# Try to find a library that was compiled with the same compiler version as we currently use.
SET(JSONCPP_NAMES ${JSONCPP_NAMES} libjson_linux-gcc-${_gcc_COMPILER_VERSION}_libmt.so)
IF (STANDALONE)
# On standalone, assume that the system installed library was compiled with the used compiler.
SET(JSONCPP_NAMES ${JSONCPP_NAMES} libjson.so)
# On standalone, assume that the system installed library was compiled with the used compiler.
SET(JSONCPP_NAMES ${JSONCPP_NAMES} libjson.so)
ENDIF (STANDALONE)
FIND_LIBRARY(JSONCPP_LIBRARY
NAMES ${JSONCPP_NAMES}

View File

@ -35,7 +35,7 @@ find_path(LLQTWEBKIT_INCLUDE_DIR llqtwebkit.h NO_SYSTEM_ENVIRONMENT_PATH HINTS $
find_library(LLQTWEBKIT_LIBRARY NAMES llqtwebkit NO_SYSTEM_ENVIRONMENT_PATH HINTS ${LLQTWEBKIT_LIBRARY_DIRS})
if (NOT PKG_CONFIG_FOUND OR NOT LLQTWEBKIT_FOUND) # If pkg-config couldn't find it, pretend we don't have pkg-config.
if (NOT PKG_CONFIG_FOUND OR NOT LLQTWEBKIT_FOUND) # If pkg-config couldn't find it, pretend we don't have pkg-config.
set(LLQTWEBKIT_LIBRARIES llqtwebkit)
get_filename_component(LLQTWEBKIT_LIBRARY_DIRS ${LLQTWEBKIT_LIBRARY} PATH)
endif (NOT PKG_CONFIG_FOUND OR NOT LLQTWEBKIT_FOUND)

View File

@ -30,12 +30,12 @@ endif (ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR)
if (ZLIB_FOUND)
if (NOT ZLIB_FIND_QUIETLY)
message(STATUS "Found ZLIB: ${ZLIB_LIBRARIES}")
SET(ZLIB_FIND_QUIETLY TRUE)
message(STATUS "Found ZLIB: ${ZLIB_LIBRARIES}")
SET(ZLIB_FIND_QUIETLY TRUE)
endif (NOT ZLIB_FIND_QUIETLY)
else (ZLIB_FOUND)
if (ZLIB_FIND_REQUIRED)
message(FATAL_ERROR "Could not find ZLIB library")
message(FATAL_ERROR "Could not find ZLIB library")
endif (ZLIB_FIND_REQUIRED)
endif (ZLIB_FOUND)

View File

@ -8,7 +8,7 @@ set(GOOGLEMOCK_INCLUDE_DIRS
${LIBS_PREBUILT_DIR}/include)
if (LINUX)
# VWR-24366: gmock is underlinked, it needs gtest.
# VWR-24366: gmock is underlinked, it needs gtest.
set(GOOGLEMOCK_LIBRARIES
gmock -Wl,--no-as-needed
gtest -Wl,--as-needed)

View File

@ -14,7 +14,7 @@ else (STANDALONE)
if (LINUX)
use_prebuilt_binary(tcmalloc)
set(TCMALLOC_LIBRARIES
tcmalloc)
tcmalloc)
set(PROFILER_LIBRARIES profiler)
set(GOOGLE_PERFTOOLS_INCLUDE_DIR
${LIBS_PREBUILT_DIR}/include)

View File

@ -8,7 +8,7 @@ set(LLPLUGIN_INCLUDE_DIRS
if (LINUX)
# In order to support using ld.gold on linux, we need to explicitely
# specify all libraries that llplugin uses.
set(LLPLUGIN_LIBRARIES llplugin pthread)
set(LLPLUGIN_LIBRARIES llplugin pthread)
else (LINUX)
set(LLPLUGIN_LIBRARIES llplugin)
set(LLPLUGIN_LIBRARIES llplugin)
endif (LINUX)

View File

@ -10,7 +10,7 @@ set(LLPRIMITIVE_INCLUDE_DIRS
${LIBS_OPEN_DIR}/llprimitive
)
if (WINDOWS)
set(LLPRIMITIVE_LIBRARIES
set(LLPRIMITIVE_LIBRARIES
debug llprimitive
optimized llprimitive
debug libcollada14dom22-d

View File

@ -13,4 +13,4 @@ set(LSCRIPT_LIBRARIES
lscript_library
)
set(LSCRIPT_EXECUTE_MONO_LIBRARIES lscript_execute_mono)
set(LSCRIPT_EXECUTE_MONO_LIBRARIES lscript_execute_mono)

View File

@ -5,19 +5,19 @@ set(NDOF ON CACHE BOOL "Use NDOF space navigator joystick library.")
if (NDOF)
if (STANDALONE)
set(NDOF_FIND_REQUIRED ON)
include(FindNDOF)
set(NDOF_FIND_REQUIRED ON)
include(FindNDOF)
else (STANDALONE)
use_prebuilt_binary(ndofdev)
use_prebuilt_binary(ndofdev)
if (WINDOWS)
set(NDOF_LIBRARY libndofdev)
elseif (DARWIN OR LINUX)
set(NDOF_LIBRARY ndofdev)
endif (WINDOWS)
if (WINDOWS)
set(NDOF_LIBRARY libndofdev)
elseif (DARWIN OR LINUX)
set(NDOF_LIBRARY ndofdev)
endif (WINDOWS)
set(NDOF_INCLUDE_DIR ${ARCH_PREBUILT_DIRS}/include/ndofdev)
set(NDOF_FOUND 1)
set(NDOF_INCLUDE_DIR ${ARCH_PREBUILT_DIRS}/include/ndofdev)
set(NDOF_FOUND 1)
endif (STANDALONE)
endif (NDOF)

View File

@ -8,21 +8,21 @@ if (STANDALONE)
include(${QT_USE_FILE})
set(QTDIR $ENV{QTDIR})
if (QTDIR AND NOT "${QT_BINARY_DIR}" STREQUAL "${QTDIR}/bin")
message(FATAL_ERROR "\"${QT_BINARY_DIR}\" is unequal \"${QTDIR}/bin\"; "
"Qt is found by looking for qmake in your PATH. "
"Please set your PATH such that 'qmake' is found in \$QTDIR/bin, "
"or unset QTDIR if the found Qt is correct.")
endif (QTDIR AND NOT "${QT_BINARY_DIR}" STREQUAL "${QTDIR}/bin")
message(FATAL_ERROR "\"${QT_BINARY_DIR}\" is unequal \"${QTDIR}/bin\"; "
"Qt is found by looking for qmake in your PATH. "
"Please set your PATH such that 'qmake' is found in \$QTDIR/bin, "
"or unset QTDIR if the found Qt is correct.")
endif (QTDIR AND NOT "${QT_BINARY_DIR}" STREQUAL "${QTDIR}/bin")
find_package(LLQtWebkit REQUIRED QUIET)
# Add the plugins.
set(QT_PLUGIN_LIBRARIES)
foreach(qlibname qgif qjpeg)
find_library(QT_PLUGIN_${qlibname} ${qlibname} PATHS ${QT_PLUGINS_DIR}/imageformats NO_DEFAULT_PATH)
if (QT_PLUGIN_${qlibname})
list(APPEND QT_PLUGIN_LIBRARIES ${QT_PLUGIN_${qlibname}})
else (QT_PLUGIN_${qtlibname})
message(FATAL_ERROR "Could not find the Qt plugin ${qlibname} in \"${QT_PLUGINS_DIR}/imageformats\"!")
endif (QT_PLUGIN_${qlibname})
find_library(QT_PLUGIN_${qlibname} ${qlibname} PATHS ${QT_PLUGINS_DIR}/imageformats NO_DEFAULT_PATH)
if (QT_PLUGIN_${qlibname})
list(APPEND QT_PLUGIN_LIBRARIES ${QT_PLUGIN_${qlibname}})
else (QT_PLUGIN_${qtlibname})
message(FATAL_ERROR "Could not find the Qt plugin ${qlibname} in \"${QT_PLUGINS_DIR}/imageformats\"!")
endif (QT_PLUGIN_${qlibname})
endforeach(qlibname)
# qjpeg depends on libjpeg
list(APPEND QT_PLUGIN_LIBRARIES jpeg)

View File

@ -1,3 +1,26 @@
#!/usr/bin/env python
##
## $LicenseInfo:firstyear=2011&license=viewerlgpl$
## Second Life Viewer Source Code
## Copyright (C) 2011, Linden Research, Inc.
##
## This library is free software; you can redistribute it and/or
## modify it under the terms of the GNU Lesser General Public
## License as published by the Free Software Foundation;
## version 2.1 of the License only.
##
## This library is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public
## License along with this library; if not, write to the Free Software
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
##
## Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
## $/LicenseInfo$
import sys
import os
import glob

View File

@ -59,15 +59,15 @@ endif (DARWIN)
# Libraries on which this application depends on
# Sort by high-level to low-level
target_link_libraries(llimage_libtest
${LLCOMMON_LIBRARIES}
${LLVFS_LIBRARIES}
${LLCOMMON_LIBRARIES}
${LLVFS_LIBRARIES}
${LLIMAGE_LIBRARIES}
${LLKDU_LIBRARIES}
${KDU_LIBRARY}
${LLIMAGEJ2COJ_LIBRARIES}
${OS_LIBRARIES}
)
if (DARWIN)
# Path inside the app bundle where we'll need to copy libraries
set(LLIMAGE_LIBTEST_DESTINATION_DIR

View File

@ -38,6 +38,7 @@
#include "llimagetga.h"
#include "llimagej2c.h"
#include "lldir.h"
#include "lldiriterator.h"
// system libraries
#include <iostream>
@ -201,7 +202,8 @@ void store_input_file(std::list<std::string> &input_filenames, const std::string
{
// If file name is a pattern, iterate to get each file name and store
std::string next_name;
while (gDirUtilp->getNextFileInDir(dir,name,next_name))
LLDirIterator iter(dir, name);
while (iter.next(next_name))
{
std::string file_name = dir + gDirUtilp->getDirDelimiter() + next_name;
input_filenames.push_back(file_name);

View File

@ -49,6 +49,7 @@
#include "lltabcontainer.h"
#include "lltextbox.h"
#include "lltexteditor.h"
#include "lltimectrl.h"
#include "llflyoutbutton.h"
#include "llfiltereditor.h"
#include "lllayoutstack.h"
@ -92,6 +93,7 @@ void LLWidgetReg::initClass(bool register_widgets)
//LLDefaultChildRegistry::Register<LLPlaceHolderPanel> placeholder("placeholder");
LLDefaultChildRegistry::Register<LLTabContainer> tab_container("tab_container");
LLDefaultChildRegistry::Register<LLTextBox> text("text");
LLDefaultChildRegistry::Register<LLTimeCtrl> time("time");
LLDefaultChildRegistry::Register<LLTextEditor> simple_text_editor("simple_text_editor");
LLDefaultChildRegistry::Register<LLUICtrl> ui_ctrl("ui_ctrl");
LLDefaultChildRegistry::Register<LLStatView> stat_view("stat_view");

View File

@ -1,3 +1,25 @@
#!/usr/bin/python
##
## $LicenseInfo:firstyear=2011&license=viewerlgpl$
## Second Life Viewer Source Code
## Copyright (C) 2011, Linden Research, Inc.
##
## This library is free software; you can redistribute it and/or
## modify it under the terms of the GNU Lesser General Public
## License as published by the Free Software Foundation;
## version 2.1 of the License only.
##
## This library is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public
## License along with this library; if not, write to the Free Software
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
##
## Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
## $/LicenseInfo$
from indra.base import llsd, lluuid
from datetime import datetime
import cllsd

View File

@ -163,7 +163,7 @@ class UUID(object):
def setFromMemoryDump(self, gdb_string):
"""
We expect to get gdb_string as four hex units. eg:
0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2
0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2
Which will be translated to:
db547d14-1b3f4bc3-9b984f71-d22f890a
Returns self.
@ -187,7 +187,7 @@ class UUID(object):
def getAsString(self):
"""
Return a different string representation of the form
AAAAAAAA-AAAABBBB-BBBBBBBB-BBCCCCCC (a 128-bit number in hex)
AAAAAAAA-AAAABBBB-BBBBBBBB-BBCCCCCC (a 128-bit number in hex)
where A=network address, B=timestamp, C=random.
"""
i1 = _binstr2int(self._bits[0:4])
@ -233,7 +233,7 @@ NULL = UUID()
def printTranslatedMemory(four_hex_uints):
"""
We expect to get the string as four hex units. eg:
0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2
0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2
Which will be translated to:
db547d14-1b3f4bc3-9b984f71-d22f890a
"""

View File

@ -1,3 +1,24 @@
#!/usr/bin/python
## $LicenseInfo:firstyear=2011&license=viewerlgpl$
## Second Life Viewer Source Code
## Copyright (C) 2011, Linden Research, Inc.
##
## This library is free software; you can redistribute it and/or
## modify it under the terms of the GNU Lesser General Public
## License as published by the Free Software Foundation;
## version 2.1 of the License only.
##
## This library is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public
## License along with this library; if not, write to the Free Software
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
##
## Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
## $/LicenseInfo$
import warnings

View File

@ -110,7 +110,7 @@ def format(format_str, context):
def _find_sub_matches(format_str):
"""@brief Find all of the substitution matches.
@param format_str the RUSS conformant format string.
@param format_str the RUSS conformant format string.
@return Returns an array of depths of arrays of positional matches in input.
"""
depth = 0

View File

@ -1,3 +1,24 @@
#!/usr/bin/python
## $LicenseInfo:firstyear=2011&license=viewerlgpl$
## Second Life Viewer Source Code
## Copyright (C) 2011, Linden Research, Inc.
##
## This library is free software; you can redistribute it and/or
## modify it under the terms of the GNU Lesser General Public
## License as published by the Free Software Foundation;
## version 2.1 of the License only.
##
## This library is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public
## License along with this library; if not, write to the Free Software
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
##
## Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
## $/LicenseInfo$
from indra.base import llsd, lluuid
from indra.ipc import siesta
import datetime, math, unittest

View File

@ -1,3 +1,24 @@
#!/usr/bin/python
## $LicenseInfo:firstyear=2011&license=viewerlgpl$
## Second Life Viewer Source Code
## Copyright (C) 2011, Linden Research, Inc.
##
## This library is free software; you can redistribute it and/or
## modify it under the terms of the GNU Lesser General Public
## License as published by the Free Software Foundation;
## version 2.1 of the License only.
##
## This library is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public
## License along with this library; if not, write to the Free Software
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
##
## Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
## $/LicenseInfo$
r"""UUID objects (universally unique identifiers) according to RFC 4122.
This module provides immutable UUID objects (class UUID) and the functions

View File

@ -24,16 +24,24 @@
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llcrashloggerlinux.h"
int main(int argc, char **argv)
{
llinfos << "Starting crash reporter." << llendl;
LLCrashLoggerLinux app;
app.parseCommandOptions(argc, argv);
app.init();
if (! app.init())
{
llwarns << "Unable to initialize application." << llendl;
return 1;
}
app.mainLoop();
app.cleanup();
llinfos << "Crash reporter finished normally." << llendl;
return 0;
}

View File

@ -30,8 +30,6 @@
#include "linden_common.h"
#include "boost/tokenizer.hpp"
#include "indra_constants.h" // CRASH_BEHAVIOR_ASK, CRASH_SETTING_NAME
#include "llerror.h"
#include "llfile.h"

View File

@ -673,7 +673,7 @@ bool LLAudioBufferFMOD::loadWAV(const std::string& filename)
return false;
}
if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB))
if (!LLAPRFile::isExist(filename, LL_APR_RPB))
{
// File not found, abort.
return false;

View File

@ -82,8 +82,7 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro
error_msg.clear();
//********************************
LLAPRFile infile ;
infile.open(in_fname,LL_APR_RB);
LLAPRFile infile(in_fname, LL_APR_RB);
//********************************
if (!infile.getFileHandle())
{
@ -233,8 +232,7 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname
S32 data_left = 0;
LLAPRFile infile ;
infile.open(in_fname,LL_APR_RB);
LLAPRFile infile(in_fname,LL_APR_RB);
if (!infile.getFileHandle())
{
llwarns << "Couldn't open temporary ogg file for writing: " << in_fname
@ -242,8 +240,7 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname
return(LLVORBISENC_SOURCE_OPEN_ERR);
}
LLAPRFile outfile ;
outfile.open(out_fname,LL_APR_WPB);
LLAPRFile outfile(out_fname, LL_APR_WPB);
if (!outfile.getFileHandle())
{
llwarns << "Couldn't open upload sound file for reading: " << in_fname

View File

@ -79,11 +79,11 @@ add_library (llcharacter ${llcharacter_SOURCE_FILES})
# Add tests
if (LL_TESTS)
include(LLAddBuildTest)
# UNIT TESTS
SET(llcharacter_TEST_SOURCE_FILES
lljoint.cpp
)
LL_ADD_PROJECT_UNIT_TESTS(llcharacter "${llcharacter_TEST_SOURCE_FILES}")
include(LLAddBuildTest)
# UNIT TESTS
SET(llcharacter_TEST_SOURCE_FILES
lljoint.cpp
)
LL_ADD_PROJECT_UNIT_TESTS(llcharacter "${llcharacter_TEST_SOURCE_FILES}")
endif (LL_TESTS)

View File

@ -219,8 +219,7 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName)
//--------------------------------------------------------------------
std::string path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,fileName);
LLAPRFile infile ;
infile.open(path, LL_APR_R);
LLAPRFile infile(path, LL_APR_R);
apr_file_t *fp = infile.getFileHandle();
if (!fp)
return E_ST_NO_XLT_FILE;

View File

@ -38,7 +38,7 @@
LLStringTable LLCharacter::sVisualParamNames(1024);
std::vector< LLCharacter* > LLCharacter::sInstances;
BOOL LLCharacter::sAllowInstancesChange = TRUE ;
//-----------------------------------------------------------------------------
// LLCharacter()
@ -51,8 +51,10 @@ LLCharacter::LLCharacter()
mAppearanceSerialNum( 0 ),
mSkeletonSerialNum( 0 )
{
mMotionController.setCharacter( this );
llassert_always(sAllowInstancesChange) ;
sInstances.push_back(this);
mMotionController.setCharacter( this );
mPauseRequest = new LLPauseRequestHandle();
}
@ -62,18 +64,29 @@ LLCharacter::LLCharacter()
// Class Destructor
//-----------------------------------------------------------------------------
LLCharacter::~LLCharacter()
{
{
for (LLVisualParam *param = getFirstVisualParam();
param;
param = getNextVisualParam())
{
delete param;
}
std::vector<LLCharacter*>::iterator iter = std::find(sInstances.begin(), sInstances.end(), this);
if (iter != sInstances.end())
U32 i ;
U32 size = sInstances.size() ;
for(i = 0 ; i < size ; i++)
{
sInstances.erase(iter);
if(sInstances[i] == this)
{
break ;
}
}
llassert_always(i < size) ;
llassert_always(sAllowInstancesChange) ;
sInstances[i] = sInstances[size - 1] ;
sInstances.pop_back() ;
}

View File

@ -266,6 +266,7 @@ public:
void setSkeletonSerialNum( U32 num ) { mSkeletonSerialNum = num; }
static std::vector< LLCharacter* > sInstances;
static BOOL sAllowInstancesChange ; //debug use
protected:
LLMotionController mMotionController;

View File

@ -467,13 +467,15 @@ LLPointer<LLJointState>& LLKeyframeMotion::getJointState(U32 index)
}
//-----------------------------------------------------------------------------
// getJoin()
// getJoint()
//-----------------------------------------------------------------------------
LLJoint* LLKeyframeMotion::getJoint(U32 index)
{
llassert_always (index < mJointStates.size());
LLJoint* joint = mJointStates[index]->getJoint();
llassert_always (joint);
//Commented out 06-28-11 by Aura.
//llassert_always (joint);
return joint;
}
@ -821,7 +823,11 @@ void LLKeyframeMotion::initializeConstraint(JointConstraint* constraint)
S32 joint_num;
LLVector3 source_pos = mCharacter->getVolumePos(shared_data->mSourceConstraintVolume, shared_data->mSourceConstraintOffset);
LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[0]);
if ( !cur_joint )
{
return;
}
F32 source_pos_offset = dist_vec(source_pos, cur_joint->getWorldPosition());
constraint->mTotalLength = constraint->mJointLengths[0] = dist_vec(cur_joint->getParent()->getWorldPosition(), source_pos);
@ -872,6 +878,10 @@ void LLKeyframeMotion::activateConstraint(JointConstraint* constraint)
for (joint_num = 1; joint_num < shared_data->mChainLength; joint_num++)
{
LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[joint_num]);
if ( !cur_joint )
{
return;
}
constraint->mPositions[joint_num] = (cur_joint->getWorldPosition() - mPelvisp->getWorldPosition()) * ~mPelvisp->getWorldRotation();
}
@ -932,6 +942,11 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
}
LLJoint* root_joint = getJoint(shared_data->mJointStateIndices[shared_data->mChainLength]);
if (! root_joint)
{
return;
}
LLVector3 root_pos = root_joint->getWorldPosition();
// LLQuaternion root_rot =
root_joint->getParent()->getWorldRotation();
@ -943,6 +958,11 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
for (joint_num = 0; joint_num <= shared_data->mChainLength; joint_num++)
{
LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[joint_num]);
if (!cur_joint)
{
return;
}
if (joint_mask[cur_joint->getJointNum()] >= (0xff >> (7 - getPriority())))
{
// skip constraint
@ -1033,7 +1053,14 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
if (shared_data->mChainLength)
{
LLQuaternion end_rot = getJoint(shared_data->mJointStateIndices[0])->getWorldRotation();
LLJoint* end_joint = getJoint(shared_data->mJointStateIndices[0]);
if (!end_joint)
{
return;
}
LLQuaternion end_rot = end_joint->getWorldRotation();
// slam start and end of chain to the proper positions (rest of chain stays put)
positions[0] = lerp(keyframe_source_pos, target_pos, weight);
@ -1042,7 +1069,14 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
// grab keyframe-specified positions of joints
for (joint_num = 1; joint_num < shared_data->mChainLength; joint_num++)
{
LLVector3 kinematic_position = getJoint(shared_data->mJointStateIndices[joint_num])->getWorldPosition() +
LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[joint_num]);
if (!cur_joint)
{
return;
}
LLVector3 kinematic_position = cur_joint->getWorldPosition() +
(source_to_target * constraint->mJointLengthFractions[joint_num]);
// convert intermediate joint positions to world coordinates
@ -1088,7 +1122,17 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
for (joint_num = shared_data->mChainLength; joint_num > 0; joint_num--)
{
LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[joint_num]);
if (!cur_joint)
{
return;
}
LLJoint* child_joint = getJoint(shared_data->mJointStateIndices[joint_num - 1]);
if (!child_joint)
{
return;
}
LLQuaternion parent_rot = cur_joint->getParent()->getWorldRotation();
LLQuaternion cur_rot = cur_joint->getWorldRotation();
@ -1122,7 +1166,6 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
cur_joint->setRotation(target_rot);
}
LLJoint* end_joint = getJoint(shared_data->mJointStateIndices[0]);
LLQuaternion end_local_rot = end_rot * ~end_joint->getParent()->getWorldRotation();
if (weight == 1.f)
@ -1150,7 +1193,13 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
//reset old joint rots
for (joint_num = 0; joint_num <= shared_data->mChainLength; joint_num++)
{
getJoint(shared_data->mJointStateIndices[joint_num])->setRotation(old_rots[joint_num]);
LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[joint_num]);
if (!cur_joint)
{
return;
}
cur_joint->setRotation(old_rots[joint_num]);
}
}
// simple positional constraint (pelvis only)
@ -1775,7 +1824,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
constraintp->mJointStateIndices[i] = -1;
for (U32 j = 0; j < mJointMotionList->getNumJointMotions(); j++)
{
if(getJoint(j) == joint)
LLJoint* constraint_joint = getJoint(j);
if ( !constraint_joint )
{
llwarns << "Invalid joint " << j << llendl;
return FALSE;
}
if(constraint_joint == joint)
{
constraintp->mJointStateIndices[i] = (S32)j;
break;

View File

@ -70,7 +70,7 @@ public:
private:
// private helper functions to wrap some asserts
LLPointer<LLJointState>& getJointState(U32 index);
LLJoint* getJoint(U32 index);
LLJoint* getJoint(U32 index );
public:
//-------------------------------------------------------------------------

View File

@ -351,8 +351,7 @@ BOOL LLKeyframeMotionParam::loadMotions()
// open the file
//-------------------------------------------------------------------------
S32 fileSize = 0;
LLAPRFile infile ;
infile.open(path, LL_APR_R, NULL, &fileSize);
LLAPRFile infile(path, LL_APR_R, &fileSize);
apr_file_t* fp = infile.getFileHandle() ;
if (!fp || fileSize == 0)
{

View File

@ -204,8 +204,7 @@ LLFSMState* LLStateDiagram::getState(U32 state_id)
BOOL LLStateDiagram::saveDotFile(const std::string& filename)
{
LLAPRFile outfile ;
outfile.open(filename, LL_APR_W);
LLAPRFile outfile(filename, LL_APR_W);
apr_file_t* dot_file = outfile.getFileHandle() ;
if (!dot_file)

View File

@ -31,6 +31,7 @@ set(llcommon_SOURCE_FILES
llallocator_heap_profile.cpp
llapp.cpp
llapr.cpp
llaprpool.cpp
llassettype.cpp
llavatarname.cpp
llbase32.cpp
@ -80,6 +81,7 @@ set(llcommon_SOURCE_FILES
llrand.cpp
llrefcount.cpp
llrun.cpp
llscopedvolatileaprpool.h
llsd.cpp
llsdserialize.cpp
llsdserialize_xml.cpp
@ -122,6 +124,7 @@ set(llcommon_HEADER_FILES
llavatarname.h
llapp.h
llapr.h
llaprpool.h
llassettype.h
llassoclist.h
llavatarconstants.h
@ -317,7 +320,8 @@ if (LL_TESTS)
LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llprocessor "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}"
"${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/setpython.py")
LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}")

View File

@ -387,8 +387,6 @@ const S32 MAP_SIM_RETURN_NULL_SIMS = 0x00010000;
const S32 MAP_SIM_PRELUDE = 0x00020000;
// Crash reporter behavior
const char* const CRASH_SETTINGS_FILE = "settings_crash_behavior.xml";
const char* const CRASH_BEHAVIOR_SETTING = "CrashSubmitBehavior";
const S32 CRASH_BEHAVIOR_ASK = 0;
const S32 CRASH_BEHAVIOR_ALWAYS_SEND = 1;
const S32 CRASH_BEHAVIOR_NEVER_SEND = 2;

View File

@ -137,10 +137,6 @@ void LLApp::commonCtor()
mOptions.append(sd);
}
// Make sure we clean up APR when we exit
// Don't need to do this if we're cleaning up APR in the destructor
//atexit(ll_cleanup_apr);
// Set the application to this instance.
sApplication = this;

View File

@ -29,212 +29,8 @@
#include "linden_common.h"
#include "llapr.h"
#include "apr_dso.h"
#include "llscopedvolatileaprpool.h"
apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool
LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool.
apr_thread_mutex_t *gLogMutexp = NULL;
apr_thread_mutex_t *gCallStacksLogMutexp = NULL;
const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAPRPool
void ll_init_apr()
{
if (!gAPRPoolp)
{
// Initialize APR and create the global pool
apr_initialize();
apr_pool_create(&gAPRPoolp, NULL);
// Initialize the logging mutex
apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
}
if(!LLAPRFile::sAPRFilePoolp)
{
LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ;
}
}
void ll_cleanup_apr()
{
LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;
if (gLogMutexp)
{
// Clean up the logging mutex
// All other threads NEED to be done before we clean up APR, so this is okay.
apr_thread_mutex_destroy(gLogMutexp);
gLogMutexp = NULL;
}
if (gCallStacksLogMutexp)
{
// Clean up the logging mutex
// All other threads NEED to be done before we clean up APR, so this is okay.
apr_thread_mutex_destroy(gCallStacksLogMutexp);
gCallStacksLogMutexp = NULL;
}
if (gAPRPoolp)
{
apr_pool_destroy(gAPRPoolp);
gAPRPoolp = NULL;
}
if (LLAPRFile::sAPRFilePoolp)
{
delete LLAPRFile::sAPRFilePoolp ;
LLAPRFile::sAPRFilePoolp = NULL ;
}
apr_terminate();
}
//
//
//LLAPRPool
//
LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
: mParent(parent),
mReleasePoolFlag(releasePoolFlag),
mMaxSize(size),
mPool(NULL)
{
createAPRPool() ;
}
LLAPRPool::~LLAPRPool()
{
releaseAPRPool() ;
}
void LLAPRPool::createAPRPool()
{
if(mPool)
{
return ;
}
mStatus = apr_pool_create(&mPool, mParent);
ll_apr_warn_status(mStatus) ;
if(mMaxSize > 0) //size is the number of blocks (which is usually 4K), NOT bytes.
{
apr_allocator_t *allocator = apr_pool_allocator_get(mPool);
if (allocator)
{
apr_allocator_max_free_set(allocator, mMaxSize) ;
}
}
}
void LLAPRPool::releaseAPRPool()
{
if(!mPool)
{
return ;
}
if(!mParent || mReleasePoolFlag)
{
apr_pool_destroy(mPool) ;
mPool = NULL ;
}
}
//virtual
apr_pool_t* LLAPRPool::getAPRPool()
{
return mPool ;
}
LLVolatileAPRPool::LLVolatileAPRPool(BOOL is_local, apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
: LLAPRPool(parent, size, releasePoolFlag),
mNumActiveRef(0),
mNumTotalRef(0),
mMutexPool(NULL),
mMutexp(NULL)
{
//create mutex
if(!is_local) //not a local apr_pool, that is: shared by multiple threads.
{
apr_pool_create(&mMutexPool, NULL); // Create a pool for mutex
apr_thread_mutex_create(&mMutexp, APR_THREAD_MUTEX_UNNESTED, mMutexPool);
}
}
LLVolatileAPRPool::~LLVolatileAPRPool()
{
//delete mutex
if(mMutexp)
{
apr_thread_mutex_destroy(mMutexp);
apr_pool_destroy(mMutexPool);
}
}
//
//define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool().
//
//virtual
apr_pool_t* LLVolatileAPRPool::getAPRPool()
{
return LLVolatileAPRPool::getVolatileAPRPool() ;
}
apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool()
{
LLScopedLock lock(mMutexp) ;
mNumTotalRef++ ;
mNumActiveRef++ ;
if(!mPool)
{
createAPRPool() ;
}
return mPool ;
}
void LLVolatileAPRPool::clearVolatileAPRPool()
{
LLScopedLock lock(mMutexp) ;
if(mNumActiveRef > 0)
{
mNumActiveRef--;
if(mNumActiveRef < 1)
{
if(isFull())
{
mNumTotalRef = 0 ;
//destroy the apr_pool.
releaseAPRPool() ;
}
else
{
//This does not actually free the memory,
//it just allows the pool to re-use this memory for the next allocation.
apr_pool_clear(mPool) ;
}
}
}
else
{
llassert_always(mNumActiveRef > 0) ;
}
//paranoia check if the pool is jammed.
//will remove the check before going to release.
llassert_always(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ;
}
BOOL LLVolatileAPRPool::isFull()
{
return mNumTotalRef > FULL_VOLATILE_APR_POOL ;
}
//---------------------------------------------------------------------
//
// LLScopedLock
@ -313,15 +109,17 @@ void ll_apr_assert_status(apr_status_t status, apr_dso_handle_t *handle)
//
LLAPRFile::LLAPRFile()
: mFile(NULL),
mCurrentFilePoolp(NULL)
mVolatileFilePoolp(NULL),
mRegularFilePoolp(NULL)
{
}
LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool)
LLAPRFile::LLAPRFile(std::string const& filename, apr_int32_t flags, S32* sizep, access_t access_type)
: mFile(NULL),
mCurrentFilePoolp(NULL)
mVolatileFilePoolp(NULL),
mRegularFilePoolp(NULL)
{
open(filename, flags, pool);
open(filename, flags, access_type, sizep);
}
LLAPRFile::~LLAPRFile()
@ -338,36 +136,58 @@ apr_status_t LLAPRFile::close()
mFile = NULL ;
}
if(mCurrentFilePoolp)
if (mVolatileFilePoolp)
{
mCurrentFilePoolp->clearVolatileAPRPool() ;
mCurrentFilePoolp = NULL ;
mVolatileFilePoolp->clearVolatileAPRPool() ;
mVolatileFilePoolp = NULL ;
}
if (mRegularFilePoolp)
{
delete mRegularFilePoolp;
mRegularFilePoolp = NULL;
}
return ret ;
}
apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool, S32* sizep)
apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, access_t access_type, S32* sizep)
{
apr_status_t s ;
llassert_always(!mFile);
llassert_always(!mVolatileFilePoolp && !mRegularFilePoolp);
//check if already open some file
llassert_always(!mFile) ;
llassert_always(!mCurrentFilePoolp) ;
apr_pool_t* apr_pool = pool ? pool->getVolatileAPRPool() : NULL ;
s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, getAPRFilePool(apr_pool));
if (s != APR_SUCCESS || !mFile)
apr_status_t status;
{
apr_pool_t* apr_file_open_pool; // The use of apr_pool_t is OK here.
// This is a temporary variable for a pool that is passed directly to apr_file_open below.
if (access_type == short_lived)
{
// Use a "volatile" thread-local pool.
mVolatileFilePoolp = &LLThreadLocalData::tldata().mVolatileAPRPool;
// Access the pool and increment its reference count.
// The reference count of LLVolatileAPRPool objects will be decremented
// again in LLAPRFile::close by calling mVolatileFilePoolp->clearVolatileAPRPool().
apr_file_open_pool = mVolatileFilePoolp->getVolatileAPRPool();
}
else
{
mRegularFilePoolp = new LLAPRPool(LLThreadLocalData::tldata().mRootPool);
apr_file_open_pool = (*mRegularFilePoolp)();
}
status = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, apr_file_open_pool);
}
if (status != APR_SUCCESS || !mFile)
{
mFile = NULL ;
close() ;
if (sizep)
{
*sizep = 0;
}
return status;
}
else if (sizep)
if (sizep)
{
S32 file_size = 0;
apr_off_t offset = 0;
@ -381,49 +201,7 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLV
*sizep = file_size;
}
if(!mCurrentFilePoolp)
{
mCurrentFilePoolp = pool ;
if(!mFile)
{
close() ;
}
}
return s ;
}
//use gAPRPoolp.
apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool)
{
apr_status_t s;
//check if already open some file
llassert_always(!mFile) ;
llassert_always(!mCurrentFilePoolp) ;
llassert_always(use_global_pool) ; //be aware of using gAPRPoolp.
s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, gAPRPoolp);
if (s != APR_SUCCESS || !mFile)
{
mFile = NULL ;
close() ;
return s;
}
return s;
}
apr_pool_t* LLAPRFile::getAPRFilePool(apr_pool_t* pool)
{
if(!pool)
{
mCurrentFilePoolp = sAPRFilePoolp ;
return mCurrentFilePoolp->getVolatileAPRPool() ;
}
return pool ;
return status;
}
// File I/O
@ -481,45 +259,6 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
//static components of LLAPRFile
//
//static
apr_status_t LLAPRFile::close(apr_file_t* file_handle, LLVolatileAPRPool* pool)
{
apr_status_t ret = APR_SUCCESS ;
if(file_handle)
{
ret = apr_file_close(file_handle);
file_handle = NULL ;
}
if(pool)
{
pool->clearVolatileAPRPool() ;
}
return ret ;
}
//static
apr_file_t* LLAPRFile::open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags)
{
apr_status_t s;
apr_file_t* file_handle ;
pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool());
if (s != APR_SUCCESS || !file_handle)
{
ll_apr_warn_status(s);
LL_WARNS("APR") << " Attempting to open filename: " << filename << LL_ENDL;
file_handle = NULL ;
close(file_handle, pool) ;
return NULL;
}
return file_handle ;
}
//static
S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
{
@ -553,13 +292,15 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
}
//static
S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes)
{
//*****************************************
apr_file_t* file_handle = open(filename, pool, APR_READ|APR_BINARY);
//*****************************************
if (!file_handle)
apr_file_t* file_handle;
LLScopedVolatileAPRPool pool;
apr_status_t s = apr_file_open(&file_handle, filename.c_str(), APR_READ|APR_BINARY, APR_OS_DEFAULT, pool);
if (s != APR_SUCCESS || !file_handle)
{
ll_apr_warn_status(s);
LL_WARNS("APR") << " while attempting to open file \"" << filename << '"' << LL_ENDL;
return 0;
}
@ -589,14 +330,13 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb
}
}
//*****************************************
close(file_handle, pool) ;
//*****************************************
apr_file_close(file_handle);
return (S32)bytes_read;
}
//static
S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes)
{
apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
if (offset < 0)
@ -605,11 +345,13 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n
offset = 0;
}
//*****************************************
apr_file_t* file_handle = open(filename, pool, flags);
//*****************************************
if (!file_handle)
apr_file_t* file_handle;
LLScopedVolatileAPRPool pool;
apr_status_t s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool);
if (s != APR_SUCCESS || !file_handle)
{
ll_apr_warn_status(s);
LL_WARNS("APR") << " while attempting to open file \"" << filename << '"' << LL_ENDL;
return 0;
}
@ -639,21 +381,18 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n
}
}
//*****************************************
LLAPRFile::close(file_handle, pool);
//*****************************************
apr_file_close(file_handle);
return (S32)bytes_written;
}
//static
bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool)
bool LLAPRFile::remove(const std::string& filename)
{
apr_status_t s;
pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
s = apr_file_remove(filename.c_str(), pool->getVolatileAPRPool());
pool->clearVolatileAPRPool() ;
LLScopedVolatileAPRPool pool;
s = apr_file_remove(filename.c_str(), pool);
if (s != APR_SUCCESS)
{
@ -665,13 +404,12 @@ bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool)
}
//static
bool LLAPRFile::rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool)
bool LLAPRFile::rename(const std::string& filename, const std::string& newname)
{
apr_status_t s;
pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
s = apr_file_rename(filename.c_str(), newname.c_str(), pool->getVolatileAPRPool());
pool->clearVolatileAPRPool() ;
LLScopedVolatileAPRPool pool;
s = apr_file_rename(filename.c_str(), newname.c_str(), pool);
if (s != APR_SUCCESS)
{
@ -683,49 +421,44 @@ bool LLAPRFile::rename(const std::string& filename, const std::string& newname,
}
//static
bool LLAPRFile::isExist(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags)
bool LLAPRFile::isExist(const std::string& filename, apr_int32_t flags)
{
apr_file_t* apr_file;
apr_file_t* file_handle;
apr_status_t s;
pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool());
LLScopedVolatileAPRPool pool;
s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool);
if (s != APR_SUCCESS || !apr_file)
if (s != APR_SUCCESS || !file_handle)
{
pool->clearVolatileAPRPool() ;
return false;
}
else
{
apr_file_close(apr_file) ;
pool->clearVolatileAPRPool() ;
apr_file_close(file_handle);
return true;
}
}
//static
S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool)
S32 LLAPRFile::size(const std::string& filename)
{
apr_file_t* apr_file;
apr_file_t* file_handle;
apr_finfo_t info;
apr_status_t s;
pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool->getVolatileAPRPool());
LLScopedVolatileAPRPool pool;
s = apr_file_open(&file_handle, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool);
if (s != APR_SUCCESS || !apr_file)
if (s != APR_SUCCESS || !file_handle)
{
pool->clearVolatileAPRPool() ;
return 0;
}
else
{
apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file);
apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, file_handle);
apr_file_close(apr_file) ;
pool->clearVolatileAPRPool() ;
apr_file_close(file_handle) ;
if (s == APR_SUCCESS)
{
@ -739,31 +472,29 @@ S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool)
}
//static
bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool)
bool LLAPRFile::makeDir(const std::string& dirname)
{
apr_status_t s;
pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool->getVolatileAPRPool());
pool->clearVolatileAPRPool() ;
LLScopedVolatileAPRPool pool;
s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool);
if (s != APR_SUCCESS)
{
ll_apr_warn_status(s);
LL_WARNS("APR") << " Attempting to make directory: " << dirname << LL_ENDL;
LL_WARNS("APR") << " while attempting to make directory: " << dirname << LL_ENDL;
return false;
}
return true;
}
//static
bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool)
bool LLAPRFile::removeDir(const std::string& dirname)
{
apr_status_t s;
pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
s = apr_file_remove(dirname.c_str(), pool->getVolatileAPRPool());
pool->clearVolatileAPRPool() ;
LLScopedVolatileAPRPool pool;
s = apr_file_remove(dirname.c_str(), pool);
if (s != APR_SUCCESS)
{

View File

@ -50,71 +50,9 @@
#include "apr_atomic.h"
#include "llstring.h"
extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp;
extern apr_thread_mutex_t* gCallStacksLogMutexp;
struct apr_dso_handle_t;
/**
* @brief initialize the common apr constructs -- apr itself, the
* global pool, and a mutex.
*/
void LL_COMMON_API ll_init_apr();
/**
* @brief Cleanup those common apr constructs.
*/
void LL_COMMON_API ll_cleanup_apr();
//
//LL apr_pool
//manage apr_pool_t, destroy allocated apr_pool in the destruction function.
//
class LL_COMMON_API LLAPRPool
{
public:
LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ;
virtual ~LLAPRPool() ;
virtual apr_pool_t* getAPRPool() ;
apr_status_t getStatus() {return mStatus ; }
protected:
void releaseAPRPool() ;
void createAPRPool() ;
protected:
apr_pool_t* mPool ; //pointing to an apr_pool
apr_pool_t* mParent ; //parent pool
apr_size_t mMaxSize ; //max size of mPool, mPool should return memory to system if allocated memory beyond this limit. However it seems not to work.
apr_status_t mStatus ; //status when creating the pool
BOOL mReleasePoolFlag ; //if set, mPool is destroyed when LLAPRPool is deleted. default value is true.
};
//
//volatile LL apr_pool
//which clears memory automatically.
//so it can not hold static data or data after memory is cleared
//
class LL_COMMON_API LLVolatileAPRPool : public LLAPRPool
{
public:
LLVolatileAPRPool(BOOL is_local = TRUE, apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE);
virtual ~LLVolatileAPRPool();
/*virtual*/ apr_pool_t* getAPRPool() ; //define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool().
apr_pool_t* getVolatileAPRPool() ;
void clearVolatileAPRPool() ;
BOOL isFull() ;
private:
S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool.
S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating.
apr_thread_mutex_t *mMutexp;
apr_pool_t *mMutexPool;
} ;
class LLAPRPool;
class LLVolatileAPRPool;
/**
* @class LLScopedLock
@ -205,15 +143,20 @@ class LL_COMMON_API LLAPRFile : boost::noncopyable
// make this non copyable since a copy closes the file
private:
apr_file_t* mFile ;
LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool.
LLVolatileAPRPool* mVolatileFilePoolp; // (Thread local) APR pool currently in use.
LLAPRPool* mRegularFilePoolp; // ...or a regular pool.
public:
enum access_t {
long_lived, // Use a global pool for long-lived file accesses.
short_lived // Use a volatile pool for short-lived file accesses.
};
LLAPRFile() ;
LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL);
LLAPRFile(std::string const& filename, apr_int32_t flags, S32* sizep = NULL, access_t access_type = short_lived);
~LLAPRFile() ;
apr_status_t open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL, S32* sizep = NULL);
apr_status_t open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool); //use gAPRPoolp.
apr_status_t open(const std::string& filename, apr_int32_t flags, access_t access_type, S32* sizep = NULL);
apr_status_t close() ;
// Returns actual offset, -1 if seek fails
@ -226,32 +169,24 @@ public:
apr_file_t* getFileHandle() {return mFile;}
private:
apr_pool_t* getAPRFilePool(apr_pool_t* pool) ;
//
//*******************************************************************************************************************************
//static components
//
public:
static LLVolatileAPRPool *sAPRFilePoolp ; //a global apr_pool for APRFile, which is used only when local pool does not exist.
private:
static apr_file_t* open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags);
static apr_status_t close(apr_file_t* file, LLVolatileAPRPool* pool) ;
static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset);
public:
// returns false if failure:
static bool remove(const std::string& filename, LLVolatileAPRPool* pool = NULL);
static bool rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool = NULL);
static bool isExist(const std::string& filename, LLVolatileAPRPool* pool = NULL, apr_int32_t flags = APR_READ);
static S32 size(const std::string& filename, LLVolatileAPRPool* pool = NULL);
static bool makeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
static bool removeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
static bool remove(const std::string& filename);
static bool rename(const std::string& filename, const std::string& newname);
static bool isExist(const std::string& filename, apr_int32_t flags = APR_READ);
static S32 size(const std::string& filename);
static bool makeDir(const std::string& dirname);
static bool removeDir(const std::string& dirname);
// Returns bytes read/written, 0 if read/write fails:
static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL);
static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); // offset<0 means append
static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes);
static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes); // offset<0 means append
//*******************************************************************************************************************************
};
@ -267,6 +202,4 @@ bool LL_COMMON_API ll_apr_warn_status(apr_status_t status, apr_dso_handle_t* han
void LL_COMMON_API ll_apr_assert_status(apr_status_t status);
void LL_COMMON_API ll_apr_assert_status(apr_status_t status, apr_dso_handle_t* handle);
extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool
#endif // LL_LLAPR_H

View File

@ -0,0 +1,202 @@
/**
* @file llaprpool.cpp
*
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2011, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*
* CHANGELOG
* and additional copyright holders.
*
* 04/04/2010
* - Initial version, written by Aleric Inglewood @ SL
*
* 10/11/2010
* - Added APR_HAS_THREADS #if's to allow creation and destruction
* of subpools by threads other than the parent pool owner.
*/
#include "linden_common.h"
#include "llerror.h"
#include "llaprpool.h"
#include "llthread.h"
// Create a subpool from parent.
void LLAPRPool::create(LLAPRPool& parent)
{
llassert(!mPool); // Must be non-initialized.
mParent = &parent;
if (!mParent) // Using the default parameter?
{
// By default use the root pool of the current thread.
mParent = &LLThreadLocalData::tldata().mRootPool;
}
llassert(mParent->mPool); // Parent must be initialized.
#if APR_HAS_THREADS
// As per the documentation of APR (ie http://apr.apache.org/docs/apr/1.4/apr__pools_8h.html):
//
// Note that most operations on pools are not thread-safe: a single pool should only be
// accessed by a single thread at any given time. The one exception to this rule is creating
// a subpool of a given pool: one or more threads can safely create subpools at the same
// time that another thread accesses the parent pool.
//
// In other words, it's safe for any thread to create a (sub)pool, independent of who
// owns the parent pool.
mOwner = apr_os_thread_current();
#else
mOwner = mParent->mOwner;
llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
#endif
apr_status_t const apr_pool_create_status = apr_pool_create(&mPool, mParent->mPool);
llassert_always(apr_pool_create_status == APR_SUCCESS);
llassert(mPool); // Initialized.
apr_pool_cleanup_register(mPool, this, &s_plain_cleanup, &apr_pool_cleanup_null);
}
// Destroy the (sub)pool, if any.
void LLAPRPool::destroy(void)
{
// Only do anything if we are not already (being) destroyed.
if (mPool)
{
#if !APR_HAS_THREADS
// If we are a root pool, then every thread may destruct us: in that case
// we have to assume that no other thread will use this pool concurrently,
// of course. Otherwise, if we are a subpool, only the thread that owns
// the parent may destruct us, since that is the pool that is still alive,
// possibly being used by others and being altered here.
llassert(!mParent || apr_os_thread_equal(mParent->mOwner, apr_os_thread_current()));
#endif
apr_pool_t* pool = mPool; // The use of apr_pool_t is OK here.
// Temporary store before destroying the pool.
mPool = NULL; // Mark that we are BEING destructed.
apr_pool_cleanup_kill(pool, this, &s_plain_cleanup);
apr_pool_destroy(pool);
}
}
bool LLAPRPool::parent_is_being_destructed(void)
{
return mParent && (!mParent->mPool || mParent->parent_is_being_destructed());
}
LLAPRInitialization::LLAPRInitialization(void)
{
static bool apr_initialized = false;
if (!apr_initialized)
{
apr_initialize();
}
apr_initialized = true;
}
bool LLAPRRootPool::sCountInitialized = false;
apr_uint32_t volatile LLAPRRootPool::sCount;
apr_thread_mutex_t* gLogMutexp;
apr_thread_mutex_t* gCallStacksLogMutexp;
LLAPRRootPool::LLAPRRootPool(void) : LLAPRInitialization(), LLAPRPool(0)
{
// sCountInitialized don't need locking because when we get here there is still only a single thread.
if (!sCountInitialized)
{
// Initialize the logging mutex
apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, mPool);
apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, mPool);
apr_status_t status = apr_atomic_init(mPool);
llassert_always(status == APR_SUCCESS);
apr_atomic_set32(&sCount, 1); // Set to 1 to account for the global root pool.
sCountInitialized = true;
// Initialize thread-local APR pool support.
// Because this recursively calls LLAPRRootPool::LLAPRRootPool(void)
// it must be done last, so that sCount is already initialized.
LLThreadLocalData::init();
}
apr_atomic_inc32(&sCount);
}
LLAPRRootPool::~LLAPRRootPool()
{
if (!apr_atomic_dec32(&sCount))
{
// The last pool was destructed. Cleanup remainder of APR.
LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;
if (gLogMutexp)
{
// Clean up the logging mutex
// All other threads NEED to be done before we clean up APR, so this is okay.
apr_thread_mutex_destroy(gLogMutexp);
gLogMutexp = NULL;
}
if (gCallStacksLogMutexp)
{
// Clean up the logging mutex
// All other threads NEED to be done before we clean up APR, so this is okay.
apr_thread_mutex_destroy(gCallStacksLogMutexp);
gCallStacksLogMutexp = NULL;
}
// Must destroy ALL, and therefore this last LLAPRRootPool, before terminating APR.
static_cast<LLAPRRootPool*>(this)->destroy();
apr_terminate();
}
}
//static
// Return a global root pool that is independent of LLThreadLocalData.
// Normally you should NOT use this. Only use for early initialization
// (before main) and deinitialization (after main).
LLAPRRootPool& LLAPRRootPool::get(void)
{
static LLAPRRootPool global_APRpool(0);
return global_APRpool;
}
void LLVolatileAPRPool::clearVolatileAPRPool()
{
llassert_always(mNumActiveRef > 0);
if (--mNumActiveRef == 0)
{
if (isOld())
{
destroy();
mNumTotalRef = 0 ;
}
else
{
// This does not actually free the memory,
// it just allows the pool to re-use this memory for the next allocation.
clear();
}
}
// Paranoia check if the pool is jammed.
llassert(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ;
}

256
indra/llcommon/llaprpool.h Normal file
View File

@ -0,0 +1,256 @@
/**
* @file llaprpool.h
* @brief Implementation of LLAPRPool
*
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2011, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*
* CHANGELOG
* and additional copyright holders.
*
* 04/04/2010
* - Initial version, written by Aleric Inglewood @ SL
*
* 10/11/2010
* - Added APR_HAS_THREADS #if's to allow creation and destruction
* of subpools by threads other than the parent pool owner.
*
* 05/02/2011
* - Fixed compilation on windows: Suppress compile warning 4996
* and include <winsock2.h> before including <ws2tcpip.h>,
* by Merov Linden @ SL.
*/
#ifndef LL_LLAPRPOOL_H
#define LL_LLAPRPOOL_H
#ifdef LL_WINDOWS
#pragma warning(push)
#pragma warning(disable:4996)
#include <winsock2.h>
#include <ws2tcpip.h> // Needed before including apr_portable.h
#pragma warning(pop)
#endif
#include "apr_portable.h"
#include "apr_pools.h"
#include "llerror.h"
extern void ll_init_apr();
/**
* @brief A wrapper around the APR memory pool API.
*
* Usage of this class should be restricted to passing it to libapr-1 function calls that need it.
*
*/
class LL_COMMON_API LLAPRPool
{
protected:
//! Pointer to the underlaying pool. NULL if not initialized.
apr_pool_t* mPool; // The use of apr_pool_t is OK here.
// This is the wrapped pointer that it is all about!
//! Pointer to the parent pool, if any. Only valid when mPool is non-zero.
LLAPRPool* mParent;
//! The thread that owns this memory pool. Only valid when mPool is non-zero.
apr_os_thread_t mOwner;
public:
/// Construct an uninitialized (destructed) pool.
LLAPRPool(void) : mPool(NULL) { }
/// Construct a subpool from an existing pool.
/// This is not a copy-constructor, this class doesn't have one!
LLAPRPool(LLAPRPool& parent) : mPool(NULL) { create(parent); }
/// Destruct the memory pool (free all of its subpools and allocated memory).
~LLAPRPool() { destroy(); }
protected:
/// Create a pool that is allocated from the Operating System. Only used by LLAPRRootPool.
LLAPRPool(int) : mPool(NULL), mParent(NULL), mOwner(apr_os_thread_current())
{
apr_status_t const apr_pool_create_status = apr_pool_create(&mPool, NULL);
llassert_always(apr_pool_create_status == APR_SUCCESS);
llassert(mPool);
apr_pool_cleanup_register(mPool, this, &s_plain_cleanup, &apr_pool_cleanup_null);
}
public:
/// Create a subpool from parent. May only be called for an uninitialized/destroyed pool.
/// The default parameter causes the root pool of the current thread to be used.
void create(LLAPRPool& parent = *static_cast<LLAPRPool*>(NULL));
/// Destroy the (sub)pool, if any.
void destroy(void);
// Use some safebool idiom (http://www.artima.com/cppsource/safebool.html) rather than operator bool.
typedef LLAPRPool* const LLAPRPool::* const bool_type;
/// Return true if the pool is initialized.
operator bool_type() const { return mPool ? &LLAPRPool::mParent : 0; }
/// Painful, but we have to either provide access to this, or wrap
/// every APR function call that needs an apr pool as argument.
/// NEVER destroy a pool that is returned by this function!
apr_pool_t* operator()(void) const // The use of apr_pool_t is OK here.
// This is the accessor for passing the pool to libapr-1 functions.
{
llassert(mPool);
llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
return mPool;
}
/// Free all memory without destructing the pool.
void clear(void)
{
llassert(mPool);
llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
apr_pool_clear(mPool);
}
// These methods would make this class 'complete' (as wrapper around the libapr
// pool functions), but we don't use memory pools in the viewer (only when
// we are forced to pass one to a libapr call), so don't define them in order
// not to encourage people to use them.
#if 0
void* palloc(size_t size)
{
llassert(mPool);
llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
return apr_palloc(mPool, size);
}
void* pcalloc(size_t size)
{
llassert(mPool);
llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
return apr_pcalloc(mPool, size);
}
#endif
private:
bool parent_is_being_destructed(void);
static apr_status_t s_plain_cleanup(void* userdata) { return static_cast<LLAPRPool*>(userdata)->plain_cleanup(); }
apr_status_t plain_cleanup(void)
{
if (mPool && // We are not being destructed,
parent_is_being_destructed()) // but our parent is.
// This means the pool is being destructed recursively by libapr
// because one of its parents is being destructed.
{
mPool = NULL; // Stop destroy() from destructing the pool again.
}
return APR_SUCCESS;
}
};
class LLAPRInitialization
{
public:
LLAPRInitialization(void);
};
/**
* @brief Root memory pool (allocates memory from the operating system).
*
* This class should only be used by LLThreadLocalData
* (and LLMutexRootPool when APR_HAS_THREADS isn't defined).
*/
class LL_COMMON_API LLAPRRootPool : public LLAPRInitialization, public LLAPRPool
{
private:
/// Construct a root memory pool. Should only be used by LLThreadLocalData and LLMutexRootPool.
friend class LLThreadLocalData;
#if !APR_HAS_THREADS
friend class LLMutexRootPool;
#endif
/// Construct a root memory pool.
/// Should only be used by LLThreadLocalData.
LLAPRRootPool(void);
~LLAPRRootPool();
private:
// Keep track of how many root pools exist and when the last one is destructed.
static bool sCountInitialized;
static apr_uint32_t volatile sCount;
public:
// Return a global root pool that is independent of LLThreadLocalData.
// Normally you should not use this. Only use for early initialization
// (before main) and deinitialization (after main).
static LLAPRRootPool& get(void);
#if APR_POOL_DEBUG
void grab_ownership(void)
{
// You need a patched libapr to use this.
// See http://web.archiveorange.com/archive/v/5XO9y2zoxUOMt6Gmi1OI
apr_pool_owner_set(mPool);
}
#endif
private:
// Used for constructing the Special Global Root Pool (returned by LLAPRRootPool::get).
// It is the same as the default constructor but omits to increment sCount. As a result,
// we must be sure that at least one other LLAPRRootPool is created before termination
// of the application (which is the case: we create one LLAPRRootPool per thread).
LLAPRRootPool(int) : LLAPRInitialization(), LLAPRPool(0) { }
};
/** Volatile memory pool
*
* 'Volatile' APR memory pool which normally only clears memory,
* and does not destroy the pool (the same pool is reused) for
* greater efficiency. However, as a safe guard the apr pool
* is destructed every FULL_VOLATILE_APR_POOL uses to allow
* the system memory to be allocated more efficiently and not
* get scattered through RAM.
*/
class LL_COMMON_API LLVolatileAPRPool : protected LLAPRPool
{
public:
LLVolatileAPRPool(void) : mNumActiveRef(0), mNumTotalRef(0) { }
void clearVolatileAPRPool(void);
bool isOld(void) const { return mNumTotalRef > FULL_VOLATILE_APR_POOL; }
bool isUnused() const { return mNumActiveRef == 0; }
private:
friend class LLScopedVolatileAPRPool;
friend class LLAPRFile;
apr_pool_t* getVolatileAPRPool(void) // The use of apr_pool_t is OK here.
{
if (!mPool) create();
++mNumActiveRef;
++mNumTotalRef;
return LLAPRPool::operator()();
}
private:
S32 mNumActiveRef; // Number of active uses of the pool.
S32 mNumTotalRef; // Number of total uses of the pool since last creation.
// Maximum number of references to LLVolatileAPRPool until the pool is recreated.
static S32 const FULL_VOLATILE_APR_POOL = 1024;
};
#endif // LL_LLAPRPOOL_H

View File

@ -30,18 +30,10 @@
#include "llmemory.h"
#include "llthread.h"
//static
BOOL LLCommon::sAprInitialized = FALSE;
//static
void LLCommon::initClass()
{
LLMemory::initClass();
if (!sAprInitialized)
{
ll_init_apr();
sAprInitialized = TRUE;
}
LLTimer::initClass();
LLThreadSafeRefCount::initThreadSafeRefCount();
// LLWorkerThread::initClass();
@ -55,10 +47,5 @@ void LLCommon::cleanupClass()
// LLWorkerThread::cleanupClass();
LLThreadSafeRefCount::cleanupThreadSafeRefCount();
LLTimer::cleanupClass();
if (sAprInitialized)
{
ll_cleanup_apr();
sAprInitialized = FALSE;
}
LLMemory::cleanupClass();
}

View File

@ -35,8 +35,6 @@ class LL_COMMON_API LLCommon
public:
static void initClass();
static void cleanupClass();
private:
static BOOL sAprInitialized;
};
#endif

View File

@ -379,7 +379,7 @@ namespace
{
/* This pattern, of returning a reference to a static function
variable, is to ensure that this global is constructed before
it is used, no matter what the global initializeation sequence
it is used, no matter what the global initialization sequence
is.
See C++ FAQ Lite, sections 10.12 through 10.14
*/
@ -866,6 +866,9 @@ You get:
*/
extern apr_thread_mutex_t* gLogMutexp;
extern apr_thread_mutex_t* gCallStacksLogMutexp;
namespace {
bool checkLevelMap(const LevelMap& map, const std::string& key,
LLError::ELevel& level)

View File

@ -39,7 +39,7 @@
Information for most users:
Code can log messages with constuctions like this:
Code can log messages with constructions like this:
LL_INFOS("StringTag") << "request to fizzbip agent " << agent_id
<< " denied due to timeout" << LL_ENDL;
@ -47,9 +47,9 @@
Messages can be logged to one of four increasing levels of concern,
using one of four "streams":
LL_DEBUGS("StringTag") - debug messages that are normally supressed
LL_INFOS("StringTag") - informational messages that are normall shown
LL_WARNS("StringTag") - warning messages that singal a problem
LL_DEBUGS("StringTag") - debug messages that are normally suppressed
LL_INFOS("StringTag") - informational messages that are normal shown
LL_WARNS("StringTag") - warning messages that signal a problem
LL_ERRS("StringTag") - error messages that are major, unrecoverable failures
The later (LL_ERRS("StringTag")) automatically crashes the process after the message
@ -90,7 +90,7 @@
WARN: LLFoo::doSomething: called with a big value for i: 283
Which messages are logged and which are supressed can be controled at run
Which messages are logged and which are suppressed can be controlled at run
time from the live file logcontrol.xml based on function, class and/or
source file. See etc/logcontrol-dev.xml for details.
@ -106,7 +106,7 @@ namespace LLError
enum ELevel
{
LEVEL_ALL = 0,
// used to indicate that all messagess should be logged
// used to indicate that all messages should be logged
LEVEL_DEBUG = 0,
LEVEL_INFO = 1,
@ -220,7 +220,7 @@ namespace LLError
// See top of file for example of how to use this
typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
// Outside a class declartion, or in class without LOG_CLASS(), this
// Outside a class declaration, or in class without LOG_CLASS(), this
// typedef causes the messages to not be associated with any class.
@ -296,5 +296,4 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
Such computation is done iff the message will be logged.
*/
#endif // LL_LLERROR_H

View File

@ -58,19 +58,15 @@ LLEventTimer::~LLEventTimer()
void LLEventTimer::updateClass()
{
std::list<LLEventTimer*> completed_timers;
for (instance_iter iter = beginInstances(); iter != endInstances(); )
{
LLInstanceTrackerScopedGuard guard;
for (instance_iter iter = guard.beginInstances(); iter != guard.endInstances(); )
{
LLEventTimer& timer = *iter++;
F32 et = timer.mEventTimer.getElapsedTimeF32();
if (timer.mEventTimer.getStarted() && et > timer.mPeriod) {
timer.mEventTimer.reset();
if ( timer.tick() )
{
completed_timers.push_back( &timer );
}
LLEventTimer& timer = *iter++;
F32 et = timer.mEventTimer.getElapsedTimeF32();
if (timer.mEventTimer.getStarted() && et > timer.mPeriod) {
timer.mEventTimer.reset();
if ( timer.tick() )
{
completed_timers.push_back( &timer );
}
}
}

View File

@ -219,15 +219,20 @@ LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name)
// static
void LLFastTimer::DeclareTimer::updateCachedPointers()
{
DeclareTimer::LLInstanceTrackerScopedGuard guard;
// propagate frame state pointers to timer declarations
for (DeclareTimer::instance_iter it = guard.beginInstances();
it != guard.endInstances();
++it)
for (instance_iter it = beginInstances(); it != endInstances(); ++it)
{
// update cached pointer
it->mFrameState = &it->mTimer.getFrameState();
}
// also update frame states of timers on stack
LLFastTimer* cur_timerp = LLFastTimer::sCurTimerData.mCurTimer;
while(cur_timerp->mLastTimerData.mCurTimer != cur_timerp)
{
cur_timerp->mFrameState = &cur_timerp->mFrameState->mTimer->getFrameState();
cur_timerp = cur_timerp->mLastTimerData.mCurTimer;
}
}
//static
@ -388,10 +393,7 @@ void LLFastTimer::NamedTimer::buildHierarchy()
// set up initial tree
{
NamedTimer::LLInstanceTrackerScopedGuard guard;
for (instance_iter it = guard.beginInstances();
it != guard.endInstances();
++it)
for (instance_iter it = beginInstances(); it != endInstances(); ++it)
{
NamedTimer& timer = *it;
if (&timer == NamedTimerFactory::instance().getRootTimer()) continue;
@ -519,10 +521,7 @@ void LLFastTimer::NamedTimer::resetFrame()
LLSD sd;
{
NamedTimer::LLInstanceTrackerScopedGuard guard;
for (NamedTimer::instance_iter it = guard.beginInstances();
it != guard.endInstances();
++it)
for (instance_iter it = beginInstances(); it != endInstances(); ++it)
{
NamedTimer& timer = *it;
FrameState& info = timer.getFrameState();
@ -559,7 +558,7 @@ void LLFastTimer::NamedTimer::resetFrame()
llassert_always(timerp->mFrameStateIndex < (S32)getFrameStateList().size());
}
// sort timers by dfs traversal order to improve cache coherency
// sort timers by DFS traversal order to improve cache coherency
std::sort(getFrameStateList().begin(), getFrameStateList().end(), SortTimersDFS());
// update pointers into framestatelist now that we've sorted it
@ -567,10 +566,7 @@ void LLFastTimer::NamedTimer::resetFrame()
// reset for next frame
{
NamedTimer::LLInstanceTrackerScopedGuard guard;
for (NamedTimer::instance_iter it = guard.beginInstances();
it != guard.endInstances();
++it)
for (instance_iter it = beginInstances(); it != endInstances(); ++it)
{
NamedTimer& timer = *it;
@ -614,10 +610,7 @@ void LLFastTimer::NamedTimer::reset()
// reset all history
{
NamedTimer::LLInstanceTrackerScopedGuard guard;
for (NamedTimer::instance_iter it = guard.beginInstances();
it != guard.endInstances();
++it)
for (instance_iter it = beginInstances(); it != endInstances(); ++it)
{
NamedTimer& timer = *it;
if (&timer != NamedTimerFactory::instance().getRootTimer())
@ -865,7 +858,7 @@ std::string LLFastTimer::sClockType = "rdtsc";
#else
//LL_COMMON_API U64 get_clock_count(); // in lltimer.cpp
// These use QueryPerformanceCounter, which is arguably fine and also works on amd architectures.
// These use QueryPerformanceCounter, which is arguably fine and also works on AMD architectures.
U32 LLFastTimer::getCPUClockCount32()
{
return (U32)(get_clock_count()>>8);

View File

@ -30,8 +30,7 @@
LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
: LLLineBuffer(),
mMaxLines(max_lines),
mMutex(NULL)
mMaxLines(max_lines)
{
mTimer.reset();
}

View File

@ -93,6 +93,8 @@ LLFolderDictionary::LLFolderDictionary()
addEntry(LLFolderType::FT_MESH, new FolderEntry("mesh", TRUE));
addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", TRUE));
addEntry(LLFolderType::FT_OUTBOX, new FolderEntry("outbox", TRUE));
addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", TRUE));
addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE));
};

View File

@ -83,8 +83,11 @@ public:
FT_MESH = 49,
FT_INBOX = 50,
FT_OUTBOX = 51,
FT_COUNT = 51,
FT_BASIC_ROOT = 52,
FT_COUNT,
FT_NONE = -1
};

View File

@ -35,14 +35,15 @@
//static
void * & LLInstanceTrackerBase::getInstances(std::type_info const & info)
{
static std::map<std::string, void *> instances;
typedef std::map<std::string, void *> InstancesMap;
static InstancesMap instances;
std::string k = info.name();
if(instances.find(k) == instances.end())
{
instances[k] = NULL;
}
return instances[k];
// std::map::insert() is just what we want here. You attempt to insert a
// (key, value) pair. If the specified key doesn't yet exist, it inserts
// the pair and returns a std::pair of (iterator, true). If the specified
// key DOES exist, insert() simply returns (iterator, false). One lookup
// handles both cases.
return instances.insert(InstancesMap::value_type(info.name(),
InstancesMap::mapped_type()))
.first->second;
}

View File

@ -29,6 +29,7 @@
#define LL_LLINSTANCETRACKER_H
#include <map>
#include <typeinfo>
#include "string_table.h"
#include <boost/utility.hpp>
@ -37,10 +38,40 @@
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/indirect_iterator.hpp>
/**
* Base class manages "class-static" data that must actually have singleton
* semantics: one instance per process, rather than one instance per module as
* sometimes happens with data simply declared static.
*/
class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable
{
protected:
static void * & getInstances(std::type_info const & info);
protected:
/// Get a process-unique void* pointer slot for the specified type_info
static void * & getInstances(std::type_info const & info);
/// Find or create a STATICDATA instance for the specified TRACKED class.
/// STATICDATA must be default-constructible.
template<typename STATICDATA, class TRACKED>
static STATICDATA& getStatic()
{
void *& instances = getInstances(typeid(TRACKED));
if (! instances)
{
instances = new STATICDATA;
}
return *static_cast<STATICDATA*>(instances);
}
/// It's not essential to derive your STATICDATA (for use with
/// getStatic()) from StaticBase; it's just that both known
/// implementations do.
struct StaticBase
{
StaticBase():
sIterationNestDepth(0)
{}
S32 sIterationNestDepth;
};
};
/// This mix-in class adds support for tracking all instances of the specified class parameter T
@ -50,15 +81,89 @@ class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable
template<typename T, typename KEY = T*>
class LLInstanceTracker : public LLInstanceTrackerBase
{
typedef typename std::map<KEY, T*> InstanceMap;
typedef LLInstanceTracker<T, KEY> MyT;
typedef boost::function<const KEY&(typename InstanceMap::value_type&)> KeyGetter;
typedef boost::function<T*(typename InstanceMap::value_type&)> InstancePtrGetter;
typedef typename std::map<KEY, T*> InstanceMap;
struct StaticData: public StaticBase
{
InstanceMap sMap;
};
static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT>(); }
static InstanceMap& getMap_() { return getStatic().sMap; }
public:
/// Dereferencing key_iter gives you a const KEY&
typedef boost::transform_iterator<KeyGetter, typename InstanceMap::iterator> key_iter;
/// Dereferencing instance_iter gives you a T&
typedef boost::indirect_iterator< boost::transform_iterator<InstancePtrGetter, typename InstanceMap::iterator> > instance_iter;
class instance_iter : public boost::iterator_facade<instance_iter, T, boost::forward_traversal_tag>
{
public:
typedef boost::iterator_facade<instance_iter, T, boost::forward_traversal_tag> super_t;
instance_iter(const typename InstanceMap::iterator& it)
: mIterator(it)
{
++getStatic().sIterationNestDepth;
}
~instance_iter()
{
--getStatic().sIterationNestDepth;
}
private:
friend class boost::iterator_core_access;
void increment() { mIterator++; }
bool equal(instance_iter const& other) const
{
return mIterator == other.mIterator;
}
T& dereference() const
{
return *(mIterator->second);
}
typename InstanceMap::iterator mIterator;
};
class key_iter : public boost::iterator_facade<key_iter, KEY, boost::forward_traversal_tag>
{
public:
typedef boost::iterator_facade<key_iter, KEY, boost::forward_traversal_tag> super_t;
key_iter(typename InstanceMap::iterator it)
: mIterator(it)
{
++getStatic().sIterationNestDepth;
}
key_iter(const key_iter& other)
: mIterator(other.mIterator)
{
++getStatic().sIterationNestDepth;
}
~key_iter()
{
--getStatic().sIterationNestDepth;
}
private:
friend class boost::iterator_core_access;
void increment() { mIterator++; }
bool equal(key_iter const& other) const
{
return mIterator == other.mIterator;
}
KEY& dereference() const
{
return const_cast<KEY&>(mIterator->first);
}
typename InstanceMap::iterator mIterator;
};
static T* getInstance(const KEY& k)
{
@ -66,57 +171,51 @@ public:
return (found == getMap_().end()) ? NULL : found->second;
}
static instance_iter beginInstances()
{
return instance_iter(getMap_().begin());
}
static instance_iter endInstances()
{
return instance_iter(getMap_().end());
}
static S32 instanceCount() { return getMap_().size(); }
static key_iter beginKeys()
{
return boost::make_transform_iterator(getMap_().begin(),
boost::bind(&InstanceMap::value_type::first, _1));
return key_iter(getMap_().begin());
}
static key_iter endKeys()
{
return boost::make_transform_iterator(getMap_().end(),
boost::bind(&InstanceMap::value_type::first, _1));
return key_iter(getMap_().end());
}
static instance_iter beginInstances()
{
return instance_iter(boost::make_transform_iterator(getMap_().begin(),
boost::bind(&InstanceMap::value_type::second, _1)));
}
static instance_iter endInstances()
{
return instance_iter(boost::make_transform_iterator(getMap_().end(),
boost::bind(&InstanceMap::value_type::second, _1)));
}
static S32 instanceCount() { return getMap_().size(); }
protected:
LLInstanceTracker(KEY key) { add_(key); }
virtual ~LLInstanceTracker() { remove_(); }
virtual ~LLInstanceTracker()
{
// it's unsafe to delete instances of this type while all instances are being iterated over.
llassert_always(getStatic().sIterationNestDepth == 0);
remove_();
}
virtual void setKey(KEY key) { remove_(); add_(key); }
virtual const KEY& getKey() const { return mKey; }
virtual const KEY& getKey() const { return mInstanceKey; }
private:
void add_(KEY key)
{
mKey = key;
mInstanceKey = key;
getMap_()[key] = static_cast<T*>(this);
}
void remove_()
{
getMap_().erase(mKey);
getMap_().erase(mInstanceKey);
}
static InstanceMap& getMap_()
{
void * & instances = getInstances(typeid(MyT));
if (! instances)
{
instances = new InstanceMap;
}
return * static_cast<InstanceMap*>(instances);
}
private:
KEY mKey;
KEY mInstanceKey;
};
/// explicit specialization for default case where KEY is T*
@ -124,73 +223,78 @@ private:
template<typename T>
class LLInstanceTracker<T, T*> : public LLInstanceTrackerBase
{
typedef typename std::set<T*> InstanceSet;
typedef LLInstanceTracker<T, T*> MyT;
typedef typename std::set<T*> InstanceSet;
struct StaticData: public StaticBase
{
InstanceSet sSet;
};
static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT>(); }
static InstanceSet& getSet_() { return getStatic().sSet; }
public:
/// Dereferencing key_iter gives you a T* (since T* is the key)
typedef typename InstanceSet::iterator key_iter;
/// Dereferencing instance_iter gives you a T&
typedef boost::indirect_iterator<key_iter> instance_iter;
/// for completeness of analogy with the generic implementation
static T* getInstance(T* k) { return k; }
static S32 instanceCount() { return getSet_().size(); }
// Instantiate this to get access to iterators for this type. It's a 'guard' in the sense
// that it treats deletes of this type as errors as long as there is an instance of
// this class alive in scope somewhere (i.e. deleting while iterating is bad).
class LLInstanceTrackerScopedGuard
class instance_iter : public boost::iterator_facade<instance_iter, T, boost::forward_traversal_tag>
{
public:
LLInstanceTrackerScopedGuard()
instance_iter(const typename InstanceSet::iterator& it)
: mIterator(it)
{
++sIterationNestDepth;
++getStatic().sIterationNestDepth;
}
~LLInstanceTrackerScopedGuard()
instance_iter(const instance_iter& other)
: mIterator(other.mIterator)
{
--sIterationNestDepth;
++getStatic().sIterationNestDepth;
}
static instance_iter beginInstances() { return instance_iter(getSet_().begin()); }
static instance_iter endInstances() { return instance_iter(getSet_().end()); }
static key_iter beginKeys() { return getSet_().begin(); }
static key_iter endKeys() { return getSet_().end(); }
~instance_iter()
{
--getStatic().sIterationNestDepth;
}
private:
friend class boost::iterator_core_access;
void increment() { mIterator++; }
bool equal(instance_iter const& other) const
{
return mIterator == other.mIterator;
}
T& dereference() const
{
return **mIterator;
}
typename InstanceSet::iterator mIterator;
};
static instance_iter beginInstances() { return instance_iter(getSet_().begin()); }
static instance_iter endInstances() { return instance_iter(getSet_().end()); }
protected:
LLInstanceTracker()
{
// it's safe but unpredictable to create instances of this type while all instances are being iterated over. I hate unpredictable. This assert will probably be turned on early in the next development cycle.
//llassert(sIterationNestDepth == 0);
// it's safe but unpredictable to create instances of this type while all instances are being iterated over. I hate unpredictable. This assert will probably be turned on early in the next development cycle.
getSet_().insert(static_cast<T*>(this));
}
virtual ~LLInstanceTracker()
{
// it's unsafe to delete instances of this type while all instances are being iterated over.
llassert(sIterationNestDepth == 0);
llassert_always(getStatic().sIterationNestDepth == 0);
getSet_().erase(static_cast<T*>(this));
}
LLInstanceTracker(const LLInstanceTracker& other)
{
//llassert(sIterationNestDepth == 0);
getSet_().insert(static_cast<T*>(this));
}
static InstanceSet& getSet_()
{
void * & instances = getInstances(typeid(MyT));
if (! instances)
{
instances = new InstanceSet;
}
return * static_cast<InstanceSet *>(instances);
}
static S32 sIterationNestDepth;
};
template <typename T> S32 LLInstanceTracker<T, T*>::sIterationNestDepth = 0;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,6 @@
#define LLMEMORY_H
#include "llmemtype.h"
#if LL_DEBUG
inline void* ll_aligned_malloc( size_t size, int align )
{
@ -105,6 +104,10 @@ inline void ll_aligned_free_32(void *p)
#define ll_aligned_free_32 free
#endif // LL_DEBUG
#ifndef __DEBUG_PRIVATE_MEM__
#define __DEBUG_PRIVATE_MEM__ 0
#endif
class LL_COMMON_API LLMemory
{
public:
@ -115,8 +118,24 @@ public:
// Return value is zero if not known.
static U64 getCurrentRSS();
static U32 getWorkingSetSize();
static void* tryToAlloc(void* address, U32 size);
static void initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure);
static void updateMemoryInfo() ;
static void logMemoryInfo(BOOL update = FALSE);
static S32 isMemoryPoolLow();
static U32 getAvailableMemKB() ;
static U32 getMaxMemKB() ;
static U32 getAllocatedMemKB() ;
private:
static char* reserveMem;
static U32 sAvailPhysicalMemInKB ;
static U32 sMaxPhysicalMemInKB ;
static U32 sAllocatedMemInKB;
static U32 sAllocatedPageSizeInKB ;
static U32 sMaxHeapSizeInKB;
static BOOL sEnableMemoryFailurePrevention;
};
//----------------------------------------------------------------------------
@ -163,6 +182,326 @@ private:
//----------------------------------------------------------------------------
//
//class LLPrivateMemoryPool defines a private memory pool for an application to use, so the application does not
//need to access the heap directly fro each memory allocation. Throught this, the allocation speed is faster,
//and reduces virtaul address space gragmentation problem.
//Note: this class is thread-safe by passing true to the constructor function. However, you do not need to do this unless
//you are sure the memory allocation and de-allocation will happen in different threads. To make the pool thread safe
//increases allocation and deallocation cost.
//
class LL_COMMON_API LLPrivateMemoryPool
{
friend class LLPrivateMemoryPoolManager ;
public:
class LL_COMMON_API LLMemoryBlock //each block is devided into slots uniformly
{
public:
LLMemoryBlock() ;
~LLMemoryBlock() ;
void init(char* buffer, U32 buffer_size, U32 slot_size) ;
void setBuffer(char* buffer, U32 buffer_size) ;
char* allocate() ;
void freeMem(void* addr) ;
bool empty() {return !mAllocatedSlots;}
bool isFull() {return mAllocatedSlots == mTotalSlots;}
bool isFree() {return !mTotalSlots;}
U32 getSlotSize()const {return mSlotSize;}
U32 getTotalSlots()const {return mTotalSlots;}
U32 getBufferSize()const {return mBufferSize;}
char* getBuffer() const {return mBuffer;}
//debug use
void resetBitMap() ;
private:
char* mBuffer;
U32 mSlotSize ; //when the block is not initialized, it is the buffer size.
U32 mBufferSize ;
U32 mUsageBits ;
U8 mTotalSlots ;
U8 mAllocatedSlots ;
U8 mDummySize ; //size of extra bytes reserved for mUsageBits.
public:
LLMemoryBlock* mPrev ;
LLMemoryBlock* mNext ;
LLMemoryBlock* mSelf ;
struct CompareAddress
{
bool operator()(const LLMemoryBlock* const& lhs, const LLMemoryBlock* const& rhs)
{
return (U32)lhs->getBuffer() < (U32)rhs->getBuffer();
}
};
};
class LL_COMMON_API LLMemoryChunk //is divided into memory blocks.
{
public:
LLMemoryChunk() ;
~LLMemoryChunk() ;
void init(char* buffer, U32 buffer_size, U32 min_slot_size, U32 max_slot_size, U32 min_block_size, U32 max_block_size) ;
void setBuffer(char* buffer, U32 buffer_size) ;
bool empty() ;
char* allocate(U32 size) ;
void freeMem(void* addr) ;
char* getBuffer() const {return mBuffer;}
U32 getBufferSize() const {return mBufferSize;}
U32 getAllocatedSize() const {return mAlloatedSize;}
bool containsAddress(const char* addr) const;
static U32 getMaxOverhead(U32 data_buffer_size, U32 min_slot_size,
U32 max_slot_size, U32 min_block_size, U32 max_block_size) ;
void dump() ;
private:
U32 getPageIndex(U32 addr) ;
U32 getBlockLevel(U32 size) ;
U16 getPageLevel(U32 size) ;
LLMemoryBlock* addBlock(U32 blk_idx) ;
void popAvailBlockList(U32 blk_idx) ;
void addToFreeSpace(LLMemoryBlock* blk) ;
void removeFromFreeSpace(LLMemoryBlock* blk) ;
void removeBlock(LLMemoryBlock* blk) ;
void addToAvailBlockList(LLMemoryBlock* blk) ;
U32 calcBlockSize(U32 slot_size);
LLMemoryBlock* createNewBlock(LLMemoryBlock* blk, U32 buffer_size, U32 slot_size, U32 blk_idx) ;
private:
LLMemoryBlock** mAvailBlockList ;//256 by mMinSlotSize
LLMemoryBlock** mFreeSpaceList;
LLMemoryBlock* mBlocks ; //index of blocks by address.
char* mBuffer ;
U32 mBufferSize ;
char* mDataBuffer ;
char* mMetaBuffer ;
U32 mMinBlockSize ;
U32 mMinSlotSize ;
U32 mMaxSlotSize ;
U32 mAlloatedSize ;
U16 mBlockLevels;
U16 mPartitionLevels;
public:
//form a linked list
LLMemoryChunk* mNext ;
LLMemoryChunk* mPrev ;
} ;
private:
LLPrivateMemoryPool(S32 type) ;
~LLPrivateMemoryPool() ;
char *allocate(U32 size) ;
void freeMem(void* addr) ;
void dump() ;
U32 getTotalAllocatedSize() ;
U32 getTotalReservedSize() {return mReservedPoolSize;}
S32 getType() const {return mType; }
bool isEmpty() const {return !mNumOfChunks; }
private:
void lock() ;
void unlock() ;
S32 getChunkIndex(U32 size) ;
LLMemoryChunk* addChunk(S32 chunk_index) ;
void checkSize(U32 asked_size) ;
void removeChunk(LLMemoryChunk* chunk) ;
U16 findHashKey(const char* addr);
void addToHashTable(LLMemoryChunk* chunk) ;
void removeFromHashTable(LLMemoryChunk* chunk) ;
void rehash() ;
bool fillHashTable(U16 start, U16 end, LLMemoryChunk* chunk) ;
LLMemoryChunk* findChunk(const char* addr) ;
void destroyPool() ;
public:
enum
{
SMALL_ALLOCATION = 0, //from 8 bytes to 2KB(exclusive), page size 2KB, max chunk size is 4MB.
MEDIUM_ALLOCATION, //from 2KB to 512KB(exclusive), page size 32KB, max chunk size 4MB
LARGE_ALLOCATION, //from 512KB to 4MB(inclusive), page size 64KB, max chunk size 16MB
SUPER_ALLOCATION //allocation larger than 4MB.
};
enum
{
STATIC = 0 , //static pool(each alllocation stays for a long time) without threading support
VOLATILE, //Volatile pool(each allocation stays for a very short time) without threading support
STATIC_THREADED, //static pool with threading support
VOLATILE_THREADED, //volatile pool with threading support
MAX_TYPES
}; //pool types
private:
LLMutex* mMutexp ;
U32 mMaxPoolSize;
U32 mReservedPoolSize ;
LLMemoryChunk* mChunkList[SUPER_ALLOCATION] ; //all memory chunks reserved by this pool, sorted by address
U16 mNumOfChunks ;
U16 mHashFactor ;
S32 mType ;
class LLChunkHashElement
{
public:
LLChunkHashElement() {mFirst = NULL ; mSecond = NULL ;}
bool add(LLMemoryChunk* chunk) ;
void remove(LLMemoryChunk* chunk) ;
LLMemoryChunk* findChunk(const char* addr) ;
bool empty() {return !mFirst && !mSecond; }
bool full() {return mFirst && mSecond; }
bool hasElement(LLMemoryChunk* chunk) {return mFirst == chunk || mSecond == chunk;}
private:
LLMemoryChunk* mFirst ;
LLMemoryChunk* mSecond ;
};
std::vector<LLChunkHashElement> mChunkHashList ;
};
class LL_COMMON_API LLPrivateMemoryPoolManager
{
private:
LLPrivateMemoryPoolManager(BOOL enabled) ;
~LLPrivateMemoryPoolManager() ;
public:
static LLPrivateMemoryPoolManager* getInstance() ;
static void initClass(BOOL enabled) ;
static void destroyClass() ;
LLPrivateMemoryPool* newPool(S32 type) ;
void deletePool(LLPrivateMemoryPool* pool) ;
private:
static LLPrivateMemoryPoolManager* sInstance ;
std::vector<LLPrivateMemoryPool*> mPoolList ;
BOOL mPrivatePoolEnabled;
public:
//debug and statistics info.
void updateStatistics() ;
U32 mTotalReservedSize ;
U32 mTotalAllocatedSize ;
public:
#if __DEBUG_PRIVATE_MEM__
static char* allocate(LLPrivateMemoryPool* poolp, U32 size, const char* function, const int line) ;
typedef std::map<char*, std::string> mem_allocation_info_t ;
static mem_allocation_info_t sMemAllocationTracker;
#else
static char* allocate(LLPrivateMemoryPool* poolp, U32 size) ;
#endif
static void freeMem(LLPrivateMemoryPool* poolp, void* addr) ;
};
//-------------------------------------------------------------------------------------
#if __DEBUG_PRIVATE_MEM__
#define ALLOCATE_MEM(poolp, size) LLPrivateMemoryPoolManager::allocate((poolp), (size), __FUNCTION__, __LINE__)
#else
#define ALLOCATE_MEM(poolp, size) LLPrivateMemoryPoolManager::allocate((poolp), (size))
#endif
#define FREE_MEM(poolp, addr) LLPrivateMemoryPoolManager::freeMem((poolp), (addr))
//-------------------------------------------------------------------------------------
//
//the below singleton is used to test the private memory pool.
//
#if 0
class LL_COMMON_API LLPrivateMemoryPoolTester
{
private:
LLPrivateMemoryPoolTester() ;
~LLPrivateMemoryPoolTester() ;
public:
static LLPrivateMemoryPoolTester* getInstance() ;
static void destroy() ;
void run(S32 type) ;
private:
void correctnessTest() ;
void performanceTest() ;
void fragmentationtest() ;
void test(U32 min_size, U32 max_size, U32 stride, U32 times, bool random_deletion, bool output_statistics) ;
void testAndTime(U32 size, U32 times) ;
#if 0
public:
void* operator new(size_t size)
{
return (void*)sPool->allocate(size) ;
}
void operator delete(void* addr)
{
sPool->freeMem(addr) ;
}
void* operator new[](size_t size)
{
return (void*)sPool->allocate(size) ;
}
void operator delete[](void* addr)
{
sPool->freeMem(addr) ;
}
#endif
private:
static LLPrivateMemoryPoolTester* sInstance;
static LLPrivateMemoryPool* sPool ;
static LLPrivateMemoryPool* sThreadedPool ;
};
#if 0
//static
void* LLPrivateMemoryPoolTester::operator new(size_t size)
{
return (void*)sPool->allocate(size) ;
}
//static
void LLPrivateMemoryPoolTester::operator delete(void* addr)
{
sPool->free(addr) ;
}
//static
void* LLPrivateMemoryPoolTester::operator new[](size_t size)
{
return (void*)sPool->allocate(size) ;
}
//static
void LLPrivateMemoryPoolTester::operator delete[](void* addr)
{
sPool->free(addr) ;
}
#endif
#endif
// LLRefCount moved to llrefcount.h
// LLPointer moved to llpointer.h

View File

@ -0,0 +1,52 @@
/**
* @file llscopedvolatileaprpool.h
* @brief Implementation of LLScopedVolatileAPRPool
*
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2011, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLSCOPEDVOLATILEAPRPOOL_H
#define LL_LLSCOPEDVOLATILEAPRPOOL_H
#include "llthread.h"
/** Scoped volatile memory pool.
*
* As the LLVolatileAPRPool should never keep allocations very
* long, its most common use is for allocations with a lifetime
* equal to it's scope.
*
* This is a convenience class that makes just a little easier to type.
*/
class LL_COMMON_API LLScopedVolatileAPRPool
{
private:
LLVolatileAPRPool& mPool;
apr_pool_t* mScopedAPRpool; // The use of apr_pool_t is OK here.
public:
LLScopedVolatileAPRPool() : mPool(LLThreadLocalData::tldata().mVolatileAPRPool), mScopedAPRpool(mPool.getVolatileAPRPool()) { }
~LLScopedVolatileAPRPool() { mPool.clearVolatileAPRPool(); }
//! @attention Only use this to pass the underlaying pointer to a libapr-1 function that requires it.
operator apr_pool_t*() const { return mScopedAPRpool; } // The use of apr_pool_t is OK here.
};
#endif

View File

@ -354,6 +354,7 @@ static unsigned get_till_eol(std::istream& input, char *buf, unsigned bufsize)
return count;
}
LLFastTimer::DeclareTimer FTM_SD_PARSE_READ_STREAM("LLSD Read Stream");
S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data)
{
XML_Status status;
@ -373,10 +374,13 @@ S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data)
{
break;
}
count = get_till_eol(input, (char *)buffer, BUFFER_SIZE);
if (!count)
{
break;
{ LLFastTimer _(FTM_SD_PARSE_READ_STREAM);
count = get_till_eol(input, (char *)buffer, BUFFER_SIZE);
if (!count)
{
break;
}
}
status = XML_ParseBuffer(mParser, count, false);
@ -716,6 +720,7 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name)
case ELEMENT_INTEGER:
{
S32 i;
// sscanf okay here with different locales - ints don't change for different locale settings like floats do.
if ( sscanf(mCurrentContent.c_str(), "%d", &i ) == 1 )
{ // See if sscanf works - it's faster
value = i;
@ -729,15 +734,19 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name)
case ELEMENT_REAL:
{
F64 r;
if ( sscanf(mCurrentContent.c_str(), "%lf", &r ) == 1 )
{ // See if sscanf works - it's faster
value = r;
}
else
{
value = LLSD(mCurrentContent).asReal();
}
value = LLSD(mCurrentContent).asReal();
// removed since this breaks when locale has decimal separator that isn't '.'
// investigated changing local to something compatible each time but deemed higher
// risk that just using LLSD.asReal() each time.
//F64 r;
//if ( sscanf(mCurrentContent.c_str(), "%lf", &r ) == 1 )
//{ // See if sscanf works - it's faster
// value = r;
//}
//else
//{
// value = LLSD(mCurrentContent).asReal();
//}
}
break;

View File

@ -100,12 +100,6 @@ private:
DELETED
} EInitState;
static void deleteSingleton()
{
delete getData().mSingletonInstance;
getData().mSingletonInstance = NULL;
}
// stores pointer to singleton instance
// and tracks initialization state of singleton
struct SingletonInstanceData
@ -120,7 +114,11 @@ private:
~SingletonInstanceData()
{
deleteSingleton();
SingletonInstanceData& data = getData();
if (data.mInitState != DELETED)
{
deleteSingleton();
}
}
};
@ -132,6 +130,14 @@ public:
data.mInitState = DELETED;
}
// Can be used to control when the singleton is deleted. Not normally needed.
static void deleteSingleton()
{
delete getData().mSingletonInstance;
getData().mSingletonInstance = NULL;
getData().mInitState = DELETED;
}
static SingletonInstanceData& getData()
{
// this is static to cache the lookup results

View File

@ -936,13 +936,18 @@ LLStringUtil::size_type LLStringUtil::getSubstitution(const std::string& instr,
{
const std::string delims (",");
// Find the first ]
size_type pos2 = instr.find(']', start);
// Find the first [
size_type pos1 = instr.find('[', start);
if (pos1 == std::string::npos)
return std::string::npos;
//Find the first ] after the initial [
size_type pos2 = instr.find(']', pos1);
if (pos2 == std::string::npos)
return std::string::npos;
// Find the last [ before ]
size_type pos1 = instr.find_last_of('[', pos2-1);
// Find the last [ before ] in case of nested [[]]
pos1 = instr.find_last_of('[', pos2-1);
if (pos1 == std::string::npos || pos1 < start)
return std::string::npos;

View File

@ -1,6 +1,6 @@
/**
* @file llsys.cpp
* @brief Impelementation of the basic system query functions.
* @brief Implementation of the basic system query functions.
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
@ -24,6 +24,10 @@
* $/LicenseInfo$
*/
#if LL_WINDOWS
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
#endif
#include "linden_common.h"
#include "llsys.h"
@ -36,22 +40,45 @@
#endif
#include "llprocessor.h"
#include "llerrorcontrol.h"
#include "llevents.h"
#include "lltimer.h"
#include "llsdserialize.h"
#include "llsdutil.h"
#include <boost/bind.hpp>
#include <boost/circular_buffer.hpp>
#include <boost/regex.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/range.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_float.hpp>
using namespace llsd;
#if LL_WINDOWS
# define WIN32_LEAN_AND_MEAN
# include <winsock2.h>
# include <windows.h>
# include <psapi.h> // GetPerformanceInfo() et al.
#elif LL_DARWIN
# include <errno.h>
# include <sys/sysctl.h>
# include <sys/utsname.h>
# include <stdint.h>
# include <Carbon/Carbon.h>
# include <stdexcept>
# include <mach/host_info.h>
# include <mach/mach_host.h>
# include <mach/task.h>
# include <mach/task_info.h>
#elif LL_LINUX
# include <errno.h>
# include <sys/utsname.h>
# include <unistd.h>
# include <sys/sysinfo.h>
# include <stdexcept>
const char MEMINFO_FILE[] = "/proc/meminfo";
#elif LL_SOLARIS
# include <stdio.h>
@ -70,6 +97,15 @@ extern int errno;
static const S32 CPUINFO_BUFFER_SIZE = 16383;
LLCPUInfo gSysCPU;
// Don't log memory info any more often than this. It also serves as our
// framerate sample size.
static const F32 MEM_INFO_THROTTLE = 20;
// Sliding window of samples. We intentionally limit the length of time we
// remember "the slowest" framerate because framerate is very slow at login.
// If we only triggered FrameWatcher logging when the session framerate
// dropped below the login framerate, we'd have very little additional data.
static const F32 MEM_INFO_WINDOW = 10*60;
#if LL_WINDOWS
#ifndef DLLVERSIONINFO
typedef struct _DllVersionInfo
@ -613,8 +649,78 @@ void LLCPUInfo::stream(std::ostream& s) const
s << "->mCPUString: " << mCPUString << std::endl;
}
// Helper class for LLMemoryInfo: accumulate stats in the form we store for
// LLMemoryInfo::getStatsMap().
class Stats
{
public:
Stats():
mStats(LLSD::emptyMap())
{}
// Store every integer type as LLSD::Integer.
template <class T>
void add(const LLSD::String& name, const T& value,
typename boost::enable_if<boost::is_integral<T> >::type* = 0)
{
mStats[name] = LLSD::Integer(value);
}
// Store every floating-point type as LLSD::Real.
template <class T>
void add(const LLSD::String& name, const T& value,
typename boost::enable_if<boost::is_float<T> >::type* = 0)
{
mStats[name] = LLSD::Real(value);
}
// Hope that LLSD::Date values are sufficiently unambiguous.
void add(const LLSD::String& name, const LLSD::Date& value)
{
mStats[name] = value;
}
LLSD get() const { return mStats; }
private:
LLSD mStats;
};
// Wrap boost::regex_match() with a function that doesn't throw.
template <typename S, typename M, typename R>
static bool regex_match_no_exc(const S& string, M& match, const R& regex)
{
try
{
return boost::regex_match(string, match, regex);
}
catch (const std::runtime_error& e)
{
LL_WARNS("LLMemoryInfo") << "error matching with '" << regex.str() << "': "
<< e.what() << ":\n'" << string << "'" << LL_ENDL;
return false;
}
}
// Wrap boost::regex_search() with a function that doesn't throw.
template <typename S, typename M, typename R>
static bool regex_search_no_exc(const S& string, M& match, const R& regex)
{
try
{
return boost::regex_search(string, match, regex);
}
catch (const std::runtime_error& e)
{
LL_WARNS("LLMemoryInfo") << "error searching with '" << regex.str() << "': "
<< e.what() << ":\n'" << string << "'" << LL_ENDL;
return false;
}
}
LLMemoryInfo::LLMemoryInfo()
{
refresh();
}
#if LL_WINDOWS
@ -638,11 +744,7 @@ static U32 LLMemoryAdjustKBResult(U32 inKB)
U32 LLMemoryInfo::getPhysicalMemoryKB() const
{
#if LL_WINDOWS
MEMORYSTATUSEX state;
state.dwLength = sizeof(state);
GlobalMemoryStatusEx(&state);
return LLMemoryAdjustKBResult((U32)(state.ullTotalPhys >> 10));
return LLMemoryAdjustKBResult(mStatsMap["Total Physical KB"].asInteger());
#elif LL_DARWIN
// This might work on Linux as well. Someone check...
@ -690,12 +792,82 @@ U32 LLMemoryInfo::getPhysicalMemoryClamped() const
void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb)
{
#if LL_WINDOWS
MEMORYSTATUSEX state;
state.dwLength = sizeof(state);
GlobalMemoryStatusEx(&state);
// Sigh, this shouldn't be a static method, then we wouldn't have to
// reload this data separately from refresh()
LLSD statsMap(loadStatsMap());
avail_physical_mem_kb = (U32)(state.ullAvailPhys/1024) ;
avail_virtual_mem_kb = (U32)(state.ullAvailVirtual/1024) ;
avail_physical_mem_kb = statsMap["Avail Physical KB"].asInteger();
avail_virtual_mem_kb = statsMap["Avail Virtual KB"].asInteger();
#elif LL_DARWIN
// mStatsMap is derived from vm_stat, look for (e.g.) "kb free":
// $ vm_stat
// Mach Virtual Memory Statistics: (page size of 4096 bytes)
// Pages free: 462078.
// Pages active: 142010.
// Pages inactive: 220007.
// Pages wired down: 159552.
// "Translation faults": 220825184.
// Pages copy-on-write: 2104153.
// Pages zero filled: 167034876.
// Pages reactivated: 65153.
// Pageins: 2097212.
// Pageouts: 41759.
// Object cache: 841598 hits of 7629869 lookups (11% hit rate)
avail_physical_mem_kb = -1 ;
avail_virtual_mem_kb = -1 ;
#elif LL_LINUX
// mStatsMap is derived from MEMINFO_FILE:
// $ cat /proc/meminfo
// MemTotal: 4108424 kB
// MemFree: 1244064 kB
// Buffers: 85164 kB
// Cached: 1990264 kB
// SwapCached: 0 kB
// Active: 1176648 kB
// Inactive: 1427532 kB
// Active(anon): 529152 kB
// Inactive(anon): 15924 kB
// Active(file): 647496 kB
// Inactive(file): 1411608 kB
// Unevictable: 16 kB
// Mlocked: 16 kB
// HighTotal: 3266316 kB
// HighFree: 721308 kB
// LowTotal: 842108 kB
// LowFree: 522756 kB
// SwapTotal: 6384632 kB
// SwapFree: 6384632 kB
// Dirty: 28 kB
// Writeback: 0 kB
// AnonPages: 528820 kB
// Mapped: 89472 kB
// Shmem: 16324 kB
// Slab: 159624 kB
// SReclaimable: 145168 kB
// SUnreclaim: 14456 kB
// KernelStack: 2560 kB
// PageTables: 5560 kB
// NFS_Unstable: 0 kB
// Bounce: 0 kB
// WritebackTmp: 0 kB
// CommitLimit: 8438844 kB
// Committed_AS: 1271596 kB
// VmallocTotal: 122880 kB
// VmallocUsed: 65252 kB
// VmallocChunk: 52356 kB
// HardwareCorrupted: 0 kB
// HugePages_Total: 0
// HugePages_Free: 0
// HugePages_Rsvd: 0
// HugePages_Surp: 0
// Hugepagesize: 2048 kB
// DirectMap4k: 434168 kB
// DirectMap2M: 477184 kB
// (could also run 'free', but easier to read a file than run a program)
avail_physical_mem_kb = -1 ;
avail_virtual_mem_kb = -1 ;
#else
//do not know how to collect available memory info for other systems.
@ -708,56 +880,283 @@ void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_v
void LLMemoryInfo::stream(std::ostream& s) const
{
// We want these memory stats to be easy to grep from the log, along with
// the timestamp. So preface each line with the timestamp and a
// distinctive marker. Without that, we'd have to search the log for the
// introducer line, then read subsequent lines, etc...
std::string pfx(LLError::utcTime() + " <mem> ");
// Max key length
size_t key_width(0);
BOOST_FOREACH(const MapEntry& pair, inMap(mStatsMap))
{
size_t len(pair.first.length());
if (len > key_width)
{
key_width = len;
}
}
// Now stream stats
BOOST_FOREACH(const MapEntry& pair, inMap(mStatsMap))
{
s << pfx << std::setw(key_width+1) << (pair.first + ':') << ' ';
LLSD value(pair.second);
if (value.isInteger())
s << std::setw(12) << value.asInteger();
else if (value.isReal())
s << std::fixed << std::setprecision(1) << value.asReal();
else if (value.isDate())
value.asDate().toStream(s);
else
s << value; // just use default LLSD formatting
s << std::endl;
}
}
LLSD LLMemoryInfo::getStatsMap() const
{
return mStatsMap;
}
LLMemoryInfo& LLMemoryInfo::refresh()
{
mStatsMap = loadStatsMap();
LL_DEBUGS("LLMemoryInfo") << "Populated mStatsMap:\n";
LLSDSerialize::toPrettyXML(mStatsMap, LL_CONT);
LL_ENDL;
return *this;
}
LLSD LLMemoryInfo::loadStatsMap()
{
// This implementation is derived from stream() code (as of 2011-06-29).
Stats stats;
// associate timestamp for analysis over time
stats.add("timestamp", LLDate::now());
#if LL_WINDOWS
MEMORYSTATUSEX state;
state.dwLength = sizeof(state);
GlobalMemoryStatusEx(&state);
s << "Percent Memory use: " << (U32)state.dwMemoryLoad << '%' << std::endl;
s << "Total Physical KB: " << (U32)(state.ullTotalPhys/1024) << std::endl;
s << "Avail Physical KB: " << (U32)(state.ullAvailPhys/1024) << std::endl;
s << "Total page KB: " << (U32)(state.ullTotalPageFile/1024) << std::endl;
s << "Avail page KB: " << (U32)(state.ullAvailPageFile/1024) << std::endl;
s << "Total Virtual KB: " << (U32)(state.ullTotalVirtual/1024) << std::endl;
s << "Avail Virtual KB: " << (U32)(state.ullAvailVirtual/1024) << std::endl;
stats.add("Percent Memory use", state.dwMemoryLoad);
stats.add("Total Physical KB", state.ullTotalPhys/1024);
stats.add("Avail Physical KB", state.ullAvailPhys/1024);
stats.add("Total page KB", state.ullTotalPageFile/1024);
stats.add("Avail page KB", state.ullAvailPageFile/1024);
stats.add("Total Virtual KB", state.ullTotalVirtual/1024);
stats.add("Avail Virtual KB", state.ullAvailVirtual/1024);
PERFORMANCE_INFORMATION perf;
perf.cb = sizeof(perf);
GetPerformanceInfo(&perf, sizeof(perf));
SIZE_T pagekb(perf.PageSize/1024);
stats.add("CommitTotal KB", perf.CommitTotal * pagekb);
stats.add("CommitLimit KB", perf.CommitLimit * pagekb);
stats.add("CommitPeak KB", perf.CommitPeak * pagekb);
stats.add("PhysicalTotal KB", perf.PhysicalTotal * pagekb);
stats.add("PhysicalAvail KB", perf.PhysicalAvailable * pagekb);
stats.add("SystemCache KB", perf.SystemCache * pagekb);
stats.add("KernelTotal KB", perf.KernelTotal * pagekb);
stats.add("KernelPaged KB", perf.KernelPaged * pagekb);
stats.add("KernelNonpaged KB", perf.KernelNonpaged * pagekb);
stats.add("PageSize KB", pagekb);
stats.add("HandleCount", perf.HandleCount);
stats.add("ProcessCount", perf.ProcessCount);
stats.add("ThreadCount", perf.ThreadCount);
PROCESS_MEMORY_COUNTERS_EX pmem;
pmem.cb = sizeof(pmem);
// GetProcessMemoryInfo() is documented to accept either
// PROCESS_MEMORY_COUNTERS* or PROCESS_MEMORY_COUNTERS_EX*, presumably
// using the redundant size info to distinguish. But its prototype
// specifically accepts PROCESS_MEMORY_COUNTERS*, and since this is a
// classic-C API, PROCESS_MEMORY_COUNTERS_EX isn't a subclass. Cast the
// pointer.
GetProcessMemoryInfo(GetCurrentProcess(), PPROCESS_MEMORY_COUNTERS(&pmem), sizeof(pmem));
stats.add("Page Fault Count", pmem.PageFaultCount);
stats.add("PeakWorkingSetSize KB", pmem.PeakWorkingSetSize/1024);
stats.add("WorkingSetSize KB", pmem.WorkingSetSize/1024);
stats.add("QutaPeakPagedPoolUsage KB", pmem.QuotaPeakPagedPoolUsage/1024);
stats.add("QuotaPagedPoolUsage KB", pmem.QuotaPagedPoolUsage/1024);
stats.add("QuotaPeakNonPagedPoolUsage KB", pmem.QuotaPeakNonPagedPoolUsage/1024);
stats.add("QuotaNonPagedPoolUsage KB", pmem.QuotaNonPagedPoolUsage/1024);
stats.add("PagefileUsage KB", pmem.PagefileUsage/1024);
stats.add("PeakPagefileUsage KB", pmem.PeakPagefileUsage/1024);
stats.add("PrivateUsage KB", pmem.PrivateUsage/1024);
#elif LL_DARWIN
uint64_t phys = 0;
size_t len = sizeof(phys);
const vm_size_t pagekb(vm_page_size / 1024);
//
// Collect the vm_stat's
//
if(sysctlbyname("hw.memsize", &phys, &len, NULL, 0) == 0)
{
s << "Total Physical KB: " << phys/1024 << std::endl;
}
else
{
s << "Unable to collect memory information";
}
#elif LL_SOLARIS
U64 phys = 0;
vm_statistics_data_t vmstat;
mach_msg_type_number_t vmstatCount = HOST_VM_INFO_COUNT;
phys = (U64)(sysconf(_SC_PHYS_PAGES)) * (U64)(sysconf(_SC_PAGESIZE)/1024);
s << "Total Physical KB: " << phys << std::endl;
#else
// *NOTE: This works on linux. What will it do on other systems?
LLFILE* meminfo = LLFile::fopen(MEMINFO_FILE,"rb");
if(meminfo)
if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t) &vmstat, &vmstatCount) != KERN_SUCCESS)
{
char line[MAX_STRING]; /* Flawfinder: ignore */
memset(line, 0, MAX_STRING);
while(fgets(line, MAX_STRING, meminfo))
{
line[strlen(line)-1] = ' '; /*Flawfinder: ignore*/
s << line;
LL_WARNS("LLMemoryInfo") << "Unable to collect memory information" << LL_ENDL;
}
else
{
stats.add("Pages free KB", pagekb * vmstat.free_count);
stats.add("Pages active KB", pagekb * vmstat.active_count);
stats.add("Pages inactive KB", pagekb * vmstat.inactive_count);
stats.add("Pages wired KB", pagekb * vmstat.wire_count);
stats.add("Pages zero fill", vmstat.zero_fill_count);
stats.add("Page reactivations", vmstat.reactivations);
stats.add("Page-ins", vmstat.pageins);
stats.add("Page-outs", vmstat.pageouts);
stats.add("Faults", vmstat.faults);
stats.add("Faults copy-on-write", vmstat.cow_faults);
stats.add("Cache lookups", vmstat.lookups);
stats.add("Cache hits", vmstat.hits);
stats.add("Page purgeable count", vmstat.purgeable_count);
stats.add("Page purges", vmstat.purges);
stats.add("Page speculative reads", vmstat.speculative_count);
}
}
//
// Collect the misc task info
//
{
task_events_info_data_t taskinfo;
unsigned taskinfoSize = sizeof(taskinfo);
if (task_info(mach_task_self(), TASK_EVENTS_INFO, (task_info_t) &taskinfo, &taskinfoSize) != KERN_SUCCESS)
{
LL_WARNS("LLMemoryInfo") << "Unable to collect task information" << LL_ENDL;
}
else
{
stats.add("Task page-ins", taskinfo.pageins);
stats.add("Task copy-on-write faults", taskinfo.cow_faults);
stats.add("Task messages sent", taskinfo.messages_sent);
stats.add("Task messages received", taskinfo.messages_received);
stats.add("Task mach system call count", taskinfo.syscalls_mach);
stats.add("Task unix system call count", taskinfo.syscalls_unix);
stats.add("Task context switch count", taskinfo.csw);
}
}
//
// Collect the basic task info
//
{
task_basic_info_64_data_t taskinfo;
unsigned taskinfoSize = sizeof(taskinfo);
if (task_info(mach_task_self(), TASK_BASIC_INFO_64, (task_info_t) &taskinfo, &taskinfoSize) != KERN_SUCCESS)
{
LL_WARNS("LLMemoryInfo") << "Unable to collect task information" << LL_ENDL;
}
else
{
stats.add("Basic suspend count", taskinfo.suspend_count);
stats.add("Basic virtual memory KB", taskinfo.virtual_size / 1024);
stats.add("Basic resident memory KB", taskinfo.resident_size / 1024);
stats.add("Basic new thread policy", taskinfo.policy);
}
}
#elif LL_SOLARIS
U64 phys = 0;
phys = (U64)(sysconf(_SC_PHYS_PAGES)) * (U64)(sysconf(_SC_PAGESIZE)/1024);
stats.add("Total Physical KB", phys);
#elif LL_LINUX
std::ifstream meminfo(MEMINFO_FILE);
if (meminfo.is_open())
{
// MemTotal: 4108424 kB
// MemFree: 1244064 kB
// Buffers: 85164 kB
// Cached: 1990264 kB
// SwapCached: 0 kB
// Active: 1176648 kB
// Inactive: 1427532 kB
// ...
// VmallocTotal: 122880 kB
// VmallocUsed: 65252 kB
// VmallocChunk: 52356 kB
// HardwareCorrupted: 0 kB
// HugePages_Total: 0
// HugePages_Free: 0
// HugePages_Rsvd: 0
// HugePages_Surp: 0
// Hugepagesize: 2048 kB
// DirectMap4k: 434168 kB
// DirectMap2M: 477184 kB
// Intentionally don't pass the boost::no_except flag. This
// boost::regex object is constructed with a string literal, so it
// should be valid every time. If it becomes invalid, we WANT an
// exception, hopefully even before the dev checks in.
boost::regex stat_rx("(.+): +([0-9]+)( kB)?");
boost::smatch matched;
std::string line;
while (std::getline(meminfo, line))
{
LL_DEBUGS("LLMemoryInfo") << line << LL_ENDL;
if (regex_match_no_exc(line, matched, stat_rx))
{
// e.g. "MemTotal: 4108424 kB"
LLSD::String key(matched[1].first, matched[1].second);
LLSD::String value_str(matched[2].first, matched[2].second);
LLSD::Integer value(0);
try
{
value = boost::lexical_cast<LLSD::Integer>(value_str);
}
catch (const boost::bad_lexical_cast&)
{
LL_WARNS("LLMemoryInfo") << "couldn't parse '" << value_str
<< "' in " << MEMINFO_FILE << " line: "
<< line << LL_ENDL;
continue;
}
// Store this statistic.
stats.add(key, value);
}
else
{
LL_WARNS("LLMemoryInfo") << "unrecognized " << MEMINFO_FILE << " line: "
<< line << LL_ENDL;
}
}
fclose(meminfo);
}
else
{
s << "Unable to collect memory information";
LL_WARNS("LLMemoryInfo") << "Unable to collect memory information" << LL_ENDL;
}
#else
LL_WARNS("LLMemoryInfo") << "Unknown system; unable to collect memory information" << LL_ENDL;
#endif
return stats.get();
}
std::ostream& operator<<(std::ostream& s, const LLOSInfo& info)
@ -778,6 +1177,143 @@ std::ostream& operator<<(std::ostream& s, const LLMemoryInfo& info)
return s;
}
class FrameWatcher
{
public:
FrameWatcher():
// Hooking onto the "mainloop" event pump gets us one call per frame.
mConnection(LLEventPumps::instance()
.obtain("mainloop")
.listen("FrameWatcher", boost::bind(&FrameWatcher::tick, this, _1))),
// Initializing mSampleStart to an invalid timestamp alerts us to skip
// trying to compute framerate on the first call.
mSampleStart(-1),
// Initializing mSampleEnd to 0 ensures that we treat the first call
// as the completion of a sample window.
mSampleEnd(0),
mFrames(0),
// Both MEM_INFO_WINDOW and MEM_INFO_THROTTLE are in seconds. We need
// the number of integer MEM_INFO_THROTTLE sample slots that will fit
// in MEM_INFO_WINDOW. Round up.
mSamples(int((MEM_INFO_WINDOW / MEM_INFO_THROTTLE) + 0.7)),
// Initializing to F32_MAX means that the first real frame will become
// the slowest ever, which sounds like a good idea.
mSlowest(F32_MAX)
{}
bool tick(const LLSD&)
{
F32 timestamp(mTimer.getElapsedTimeF32());
// Count this frame in the interval just completed.
++mFrames;
// Have we finished a sample window yet?
if (timestamp < mSampleEnd)
{
// no, just keep waiting
return false;
}
// Set up for next sample window. Capture values for previous frame in
// local variables and reset data members.
U32 frames(mFrames);
F32 sampleStart(mSampleStart);
// No frames yet in next window
mFrames = 0;
// which starts right now
mSampleStart = timestamp;
// and ends MEM_INFO_THROTTLE seconds in the future
mSampleEnd = mSampleStart + MEM_INFO_THROTTLE;
// On the very first call, that's all we can do, no framerate
// computation is possible.
if (sampleStart < 0)
{
return false;
}
// How long did this actually take? As framerate slows, the duration
// of the frame we just finished could push us WELL beyond our desired
// sample window size.
F32 elapsed(timestamp - sampleStart);
F32 framerate(frames/elapsed);
// Remember previous slowest framerate because we're just about to
// update it.
F32 slowest(mSlowest);
// Remember previous number of samples.
boost::circular_buffer<F32>::size_type prevSize(mSamples.size());
// Capture new framerate in our samples buffer. Once the buffer is
// full (after MEM_INFO_WINDOW seconds), this will displace the oldest
// sample. ("So they all rolled over, and one fell out...")
mSamples.push_back(framerate);
// Calculate the new minimum framerate. I know of no way to update a
// rolling minimum without ever rescanning the buffer. But since there
// are only a few tens of items in this buffer, rescanning it is
// probably cheaper (and certainly easier to reason about) than
// attempting to optimize away some of the scans.
mSlowest = framerate; // pick an arbitrary entry to start
for (boost::circular_buffer<F32>::const_iterator si(mSamples.begin()), send(mSamples.end());
si != send; ++si)
{
if (*si < mSlowest)
{
mSlowest = *si;
}
}
// We're especially interested in memory as framerate drops. Only log
// when framerate drops below the slowest framerate we remember.
// (Should always be true for the end of the very first sample
// window.)
if (framerate >= slowest)
{
return false;
}
// Congratulations, we've hit a new low. :-P
LL_INFOS("FrameWatcher") << ' ';
if (! prevSize)
{
LL_CONT << "initial framerate ";
}
else
{
LL_CONT << "slowest framerate for last " << int(prevSize * MEM_INFO_THROTTLE)
<< " seconds ";
}
LL_CONT << std::fixed << std::setprecision(1) << framerate << '\n'
<< LLMemoryInfo() << LL_ENDL;
return false;
}
private:
// Storing the connection in an LLTempBoundListener ensures it will be
// disconnected when we're destroyed.
LLTempBoundListener mConnection;
// Track elapsed time
LLTimer mTimer;
// Some of what you see here is in fact redundant with functionality you
// can get from LLTimer. Unfortunately the LLTimer API is missing the
// feature we need: has at least the stated interval elapsed, and if so,
// exactly how long has passed? So we have to do it by hand, sigh.
// Time at start, end of sample window
F32 mSampleStart, mSampleEnd;
// Frames this sample window
U32 mFrames;
// Sliding window of framerate samples
boost::circular_buffer<F32> mSamples;
// Slowest framerate in mSamples
F32 mSlowest;
};
// Need an instance of FrameWatcher before it does any good
static FrameWatcher sFrameWatcher;
BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile)
{
std::string tmpfile;

View File

@ -36,6 +36,7 @@
// llinfos << info << llendl;
//
#include "llsd.h"
#include <iosfwd>
#include <string>
@ -117,6 +118,27 @@ public:
//get the available memory infomation in KiloBytes.
static void getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb);
// Retrieve a map of memory statistics. The keys of the map are platform-
// dependent. The values are in kilobytes to try to avoid integer overflow.
LLSD getStatsMap() const;
// Re-fetch memory data (as reported by stream() and getStatsMap()) from the
// system. Normally this is fetched at construction time. Return (*this)
// to permit usage of the form:
// @code
// LLMemoryInfo info;
// ...
// info.refresh().getStatsMap();
// @endcode
LLMemoryInfo& refresh();
private:
// set mStatsMap
static LLSD loadStatsMap();
// Memory stats for getStatsMap().
LLSD mStatsMap;
};

View File

@ -36,6 +36,12 @@
#include <sched.h>
#endif
#if !LL_DARWIN
U32 ll_thread_local local_thread_ID = 0;
#endif
U32 LLThread::sIDIter = 0;
//----------------------------------------------------------------------------
// Usage:
// void run_func(LLThread* thread)
@ -56,12 +62,6 @@
//
//----------------------------------------------------------------------------
#if !LL_DARWIN
U32 ll_thread_local sThreadID = 0;
#endif
U32 LLThread::sIDIter = 0;
LL_COMMON_API void assert_main_thread()
{
static U32 s_thread_id = LLThread::currentID();
@ -79,9 +79,12 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
LLThread *threadp = (LLThread *)datap;
#if !LL_DARWIN
sThreadID = threadp->mID;
local_thread_ID = threadp->mID;
#endif
// Create a thread local data.
LLThreadLocalData::create(threadp);
// Run the user supplied function
threadp->run();
@ -94,40 +97,22 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
}
LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
mPaused(FALSE),
LLThread::LLThread(std::string const& name) :
mPaused(false),
mName(name),
mAPRThreadp(NULL),
mStatus(STOPPED)
mStatus(STOPPED),
mThreadLocalData(NULL)
{
mID = ++sIDIter;
mID = ++sIDIter; //flaw: assume this is called only in the main thread!
// Thread creation probably CAN be paranoid about APR being initialized, if necessary
if (poolp)
{
mIsLocalPool = FALSE;
mAPRPoolp = poolp;
}
else
{
mIsLocalPool = TRUE;
apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
}
mRunCondition = new LLCondition(mAPRPoolp);
mLocalAPRFilePoolp = NULL ;
mRunCondition = new LLCondition;
}
LLThread::~LLThread()
{
shutdown();
if(mLocalAPRFilePoolp)
{
delete mLocalAPRFilePoolp ;
mLocalAPRFilePoolp = NULL ;
}
}
void LLThread::shutdown()
@ -164,7 +149,7 @@ void LLThread::shutdown()
if (!isStopped())
{
// This thread just wouldn't stop, even though we gave it time
//llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl;
//llwarns << "LLThread::shutdown() exiting thread before clean exit!" << llendl;
// Put a stake in its heart.
apr_thread_exit(mAPRThreadp, -1);
return;
@ -174,15 +159,8 @@ void LLThread::shutdown()
delete mRunCondition;
mRunCondition = 0;
if (mIsLocalPool && mAPRPoolp)
{
apr_pool_destroy(mAPRPoolp);
mAPRPoolp = 0;
}
}
void LLThread::start()
{
llassert(isStopped());
@ -191,7 +169,7 @@ void LLThread::start()
mStatus = RUNNING;
apr_status_t status =
apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);
apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, tldata().mRootPool());
if(status == APR_SUCCESS)
{
@ -216,7 +194,7 @@ void LLThread::pause()
if (!mPaused)
{
// this will cause the thread to stop execution as soon as checkPause() is called
mPaused = 1; // Does not need to be atomic since this is only set/unset from the main thread
mPaused = true; // Does not need to be atomic since this is only set/unset from the main thread
}
}
@ -224,7 +202,7 @@ void LLThread::unpause()
{
if (mPaused)
{
mPaused = 0;
mPaused = false;
}
wake(); // wake up the thread if necessary
@ -301,115 +279,76 @@ void LLThread::wakeLocked()
}
}
//============================================================================
LLMutex::LLMutex(apr_pool_t *poolp) :
mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD)
{
//if (poolp)
//{
// mIsLocalPool = FALSE;
// mAPRPoolp = poolp;
//}
//else
{
mIsLocalPool = TRUE;
apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
}
apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
}
LLMutex::~LLMutex()
{
#if MUTEX_DEBUG
llassert_always(!isLocked()); // better not be locked!
#ifdef SHOW_ASSERT
// This allows the use of llassert(is_main_thread()) to assure the current thread is the main thread.
static apr_os_thread_t main_thread_id;
LL_COMMON_API bool is_main_thread(void) { return apr_os_thread_equal(main_thread_id, apr_os_thread_current()); }
#endif
apr_thread_mutex_destroy(mAPRMutexp);
mAPRMutexp = NULL;
if (mIsLocalPool)
{
apr_pool_destroy(mAPRPoolp);
}
}
// The thread private handle to access the LLThreadLocalData instance.
apr_threadkey_t* LLThreadLocalData::sThreadLocalDataKey;
void LLMutex::lock()
//static
void LLThreadLocalData::init(void)
{
#if LL_DARWIN
if (mLockingThread == LLThread::currentID())
#else
if (mLockingThread == sThreadID)
#endif
{ //redundant lock
mCount++;
// Only do this once.
if (sThreadLocalDataKey)
{
return;
}
apr_thread_mutex_lock(mAPRMutexp);
#if MUTEX_DEBUG
// Have to have the lock before we can access the debug info
U32 id = LLThread::currentID();
if (mIsLocked[id] != FALSE)
llerrs << "Already locked in Thread: " << id << llendl;
mIsLocked[id] = TRUE;
#endif
#if LL_DARWIN
mLockingThread = LLThread::currentID();
#else
mLockingThread = sThreadID;
apr_status_t status = apr_threadkey_private_create(&sThreadLocalDataKey, &LLThreadLocalData::destroy, LLAPRRootPool::get()());
ll_apr_assert_status(status); // Or out of memory, or system-imposed limit on the
// total number of keys per process {PTHREAD_KEYS_MAX}
// has been exceeded.
// Create the thread-local data for the main thread (this function is called by the main thread).
LLThreadLocalData::create(NULL);
#ifdef SHOW_ASSERT
// This function is called by the main thread.
main_thread_id = apr_os_thread_current();
#endif
}
void LLMutex::unlock()
// This is called once for every thread when the thread is destructed.
//static
void LLThreadLocalData::destroy(void* thread_local_data)
{
if (mCount > 0)
{ //not the root unlock
mCount--;
return;
}
#if MUTEX_DEBUG
// Access the debug info while we have the lock
U32 id = LLThread::currentID();
if (mIsLocked[id] != TRUE)
llerrs << "Not locked in Thread: " << id << llendl;
mIsLocked[id] = FALSE;
#endif
mLockingThread = NO_THREAD;
apr_thread_mutex_unlock(mAPRMutexp);
delete static_cast<LLThreadLocalData*>(thread_local_data);
}
bool LLMutex::isLocked()
//static
void LLThreadLocalData::create(LLThread* threadp)
{
apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp);
if (APR_STATUS_IS_EBUSY(status))
LLThreadLocalData* new_tld = new LLThreadLocalData;
if (threadp)
{
return true;
}
else
{
apr_thread_mutex_unlock(mAPRMutexp);
return false;
threadp->mThreadLocalData = new_tld;
}
apr_status_t status = apr_threadkey_private_set(new_tld, sThreadLocalDataKey);
llassert_always(status == APR_SUCCESS);
}
U32 LLMutex::lockingThread() const
//static
LLThreadLocalData& LLThreadLocalData::tldata(void)
{
return mLockingThread;
if (!sThreadLocalDataKey)
{
LLThreadLocalData::init();
}
void* data;
apr_status_t status = apr_threadkey_private_get(&data, sThreadLocalDataKey);
llassert_always(status == APR_SUCCESS);
return *static_cast<LLThreadLocalData*>(data);
}
//============================================================================
LLCondition::LLCondition(apr_pool_t *poolp) :
LLMutex(poolp)
LLCondition::LLCondition(LLAPRPool& parent) : LLMutex(parent)
{
// base class (LLMutex) has already ensured that mAPRPoolp is set up.
apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
apr_thread_cond_create(&mAPRCondp, mPool());
}
@ -422,15 +361,6 @@ LLCondition::~LLCondition()
void LLCondition::wait()
{
if (!isLocked())
{ //mAPRMutexp MUST be locked before calling apr_thread_cond_wait
apr_thread_mutex_lock(mAPRMutexp);
#if MUTEX_DEBUG
// avoid asserts on destruction in non-release builds
U32 id = LLThread::currentID();
mIsLocked[id] = TRUE;
#endif
}
apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
}
@ -445,6 +375,44 @@ void LLCondition::broadcast()
}
//============================================================================
LLMutexBase::LLMutexBase() :
mLockingThread(NO_THREAD),
mCount(0)
{
}
void LLMutexBase::lock()
{
#if LL_DARWIN
if (mLockingThread == LLThread::currentID())
#else
if (mLockingThread == local_thread_ID)
#endif
{ //redundant lock
mCount++;
return;
}
apr_thread_mutex_lock(mAPRMutexp);
#if LL_DARWIN
mLockingThread = LLThread::currentID();
#else
mLockingThread = local_thread_ID;
#endif
}
void LLMutexBase::unlock()
{
if (mCount > 0)
{ //not the root unlock
mCount--;
return;
}
mLockingThread = NO_THREAD;
apr_thread_mutex_unlock(mAPRMutexp);
}
//----------------------------------------------------------------------------
@ -456,7 +424,7 @@ void LLThreadSafeRefCount::initThreadSafeRefCount()
{
if (!sMutex)
{
sMutex = new LLMutex(0);
sMutex = new LLMutex;
}
}

View File

@ -29,7 +29,13 @@
#include "llapp.h"
#include "llapr.h"
#include "llmemory.h"
#include "apr_thread_cond.h"
#include "llaprpool.h"
#ifdef SHOW_ASSERT
extern LL_COMMON_API bool is_main_thread(void);
#endif
class LLThread;
class LLMutex;
@ -41,6 +47,22 @@ class LLCondition;
#define ll_thread_local __thread
#endif
class LL_COMMON_API LLThreadLocalData
{
private:
static apr_threadkey_t* sThreadLocalDataKey;
public:
// Thread-local memory pools.
LLAPRRootPool mRootPool;
LLVolatileAPRPool mVolatileAPRPool;
static void init(void);
static void destroy(void* thread_local_data);
static void create(LLThread* pthread);
static LLThreadLocalData& tldata(void);
};
class LL_COMMON_API LLThread
{
private:
@ -54,7 +76,7 @@ public:
QUITTING= 2 // Someone wants this thread to quit
} EThreadStatus;
LLThread(const std::string& name, apr_pool_t *poolp = NULL);
LLThread(std::string const& name);
virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state.
virtual void shutdown(); // stops the thread
@ -69,7 +91,7 @@ public:
// Called from MAIN THREAD.
void pause();
void unpause();
bool isPaused() { return isStopped() || mPaused == TRUE; }
bool isPaused() { return isStopped() || mPaused; }
// Cause the thread to wake up and check its condition
void wake();
@ -83,13 +105,11 @@ public:
// this kicks off the apr thread
void start(void);
apr_pool_t *getAPRPool() { return mAPRPoolp; }
LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; }
U32 getID() const { return mID; }
// Return thread-local data for the current thread.
static LLThreadLocalData& tldata(void) { return LLThreadLocalData::tldata(); }
private:
BOOL mPaused;
bool mPaused;
// static function passed to APR thread creation routine
static void *APR_THREAD_FUNC staticRun(apr_thread_t *apr_threadp, void *datap);
@ -99,15 +119,11 @@ protected:
LLCondition* mRunCondition;
apr_thread_t *mAPRThreadp;
apr_pool_t *mAPRPoolp;
BOOL mIsLocalPool;
EThreadStatus mStatus;
U32 mID;
//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
// otherwise it will cause severe memory leaking!!! --bao
LLVolatileAPRPool *mLocalAPRFilePoolp ;
friend void LLThreadLocalData::create(LLThread* threadp);
LLThreadLocalData* mThreadLocalData;
void setQuitting();
@ -137,7 +153,15 @@ protected:
#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
class LL_COMMON_API LLMutex
#ifdef MUTEX_DEBUG
// We really shouldn't be using recursive locks. Make sure of that in debug mode.
#define MUTEX_FLAG APR_THREAD_MUTEX_UNNESTED
#else
// Use the fastest platform-optimal lock behavior (can be recursive or non-recursive).
#define MUTEX_FLAG APR_THREAD_MUTEX_DEFAULT
#endif
class LL_COMMON_API LLMutexBase
{
public:
typedef enum
@ -145,32 +169,73 @@ public:
NO_THREAD = 0xFFFFFFFF
} e_locking_thread;
LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex
virtual ~LLMutex();
void lock(); // blocks
void unlock();
bool isLocked(); // non-blocking, but does do a lock/unlock so not free
U32 lockingThread() const; //get ID of locking thread
LLMutexBase() ;
void lock() ;
void unlock() ;
// Returns true if lock was obtained successfully.
bool trylock() { return !APR_STATUS_IS_EBUSY(apr_thread_mutex_trylock(mAPRMutexp)); }
// non-blocking, but does do a lock/unlock so not free
bool isLocked() { bool is_not_locked = trylock(); if (is_not_locked) unlock(); return !is_not_locked; }
protected:
apr_thread_mutex_t *mAPRMutexp;
// mAPRMutexp is initialized and uninitialized in the derived class.
apr_thread_mutex_t* mAPRMutexp;
mutable U32 mCount;
mutable U32 mLockingThread;
apr_pool_t *mAPRPoolp;
BOOL mIsLocalPool;
#if MUTEX_DEBUG
std::map<U32, BOOL> mIsLocked;
#endif
};
class LL_COMMON_API LLMutex : public LLMutexBase
{
public:
LLMutex(LLAPRPool& parent = LLThread::tldata().mRootPool) : mPool(parent)
{
apr_thread_mutex_create(&mAPRMutexp, MUTEX_FLAG, mPool());
}
~LLMutex()
{
llassert(!isLocked()); // better not be locked!
apr_thread_mutex_destroy(mAPRMutexp);
mAPRMutexp = NULL;
}
protected:
LLAPRPool mPool;
};
#if APR_HAS_THREADS
// No need to use a root pool in this case.
typedef LLMutex LLMutexRootPool;
#else // APR_HAS_THREADS
class LL_COMMON_API LLMutexRootPool : public LLMutexBase
{
public:
LLMutexRootPool(void)
{
apr_thread_mutex_create(&mAPRMutexp, MUTEX_FLAG, mRootPool());
}
~LLMutexRootPool()
{
#if APR_POOL_DEBUG
// It is allowed to destruct root pools from a different thread.
mRootPool.grab_ownership();
#endif
llassert(!isLocked());
apr_thread_mutex_destroy(mAPRMutexp);
mAPRMutexp = NULL;
}
protected:
LLAPRRootPool mRootPool;
};
#endif // APR_HAS_THREADS
// Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
class LL_COMMON_API LLCondition : public LLMutex
{
public:
LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well.
LLCondition(LLAPRPool& parent = LLThread::tldata().mRootPool);
~LLCondition();
void wait(); // blocks
@ -181,10 +246,10 @@ protected:
apr_thread_cond_t *mAPRCondp;
};
class LLMutexLock
class LL_COMMON_API LLMutexLock
{
public:
LLMutexLock(LLMutex* mutex)
LLMutexLock(LLMutexBase* mutex)
{
mMutex = mutex;
mMutex->lock();
@ -194,7 +259,7 @@ public:
mMutex->unlock();
}
private:
LLMutex* mMutex;
LLMutexBase* mMutex;
};
//============================================================================

View File

@ -34,19 +34,11 @@
//-----------------------------------------------------------------------------
LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * pool, unsigned int capacity):
mOwnsPool(pool == 0),
mPool(pool),
LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(unsigned int capacity):
mQueue(0)
{
if(mOwnsPool) {
apr_status_t status = apr_pool_create(&mPool, 0);
if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate pool");
} else {
; // No op.
}
apr_status_t status = apr_queue_create(&mQueue, capacity, mPool);
mPool.create();
apr_status_t status = apr_queue_create(&mQueue, capacity, mPool());
if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate queue");
}
@ -59,7 +51,6 @@ LLThreadSafeQueueImplementation::~LLThreadSafeQueueImplementation()
" elements;" << "memory will be leaked" << LL_ENDL;
apr_queue_term(mQueue);
}
if(mOwnsPool && (mPool != 0)) apr_pool_destroy(mPool);
}

View File

@ -30,9 +30,9 @@
#include <string>
#include <stdexcept>
#include "llaprpool.h"
struct apr_pool_t; // From apr_pools.h
class LLThreadSafeQueueImplementation; // See below.
@ -75,7 +75,7 @@ struct apr_queue_t; // From apr_queue.h
class LL_COMMON_API LLThreadSafeQueueImplementation
{
public:
LLThreadSafeQueueImplementation(apr_pool_t * pool, unsigned int capacity);
LLThreadSafeQueueImplementation(unsigned int capacity);
~LLThreadSafeQueueImplementation();
void pushFront(void * element);
bool tryPushFront(void * element);
@ -84,8 +84,7 @@ public:
size_t size();
private:
bool mOwnsPool;
apr_pool_t * mPool;
LLAPRPool mPool; // The pool used for mQueue.
apr_queue_t * mQueue;
};
@ -99,9 +98,8 @@ class LLThreadSafeQueue
public:
typedef ElementT value_type;
// If the pool is set to NULL one will be allocated and managed by this
// queue.
LLThreadSafeQueue(apr_pool_t * pool = 0, unsigned int capacity = 1024);
// Constructor.
LLThreadSafeQueue(unsigned int capacity = 1024);
// Add an element to the front of queue (will block if the queue has
// reached capacity).
@ -139,8 +137,8 @@ private:
template<typename ElementT>
LLThreadSafeQueue<ElementT>::LLThreadSafeQueue(apr_pool_t * pool, unsigned int capacity):
mImplementation(pool, capacity)
LLThreadSafeQueue<ElementT>::LLThreadSafeQueue(unsigned int capacity) :
mImplementation(capacity)
{
; // No op.
}

6
indra/llcommon/llversionviewer.h Normal file → Executable file
View File

@ -27,9 +27,9 @@
#ifndef LL_LLVERSIONVIEWER_H
#define LL_LLVERSIONVIEWER_H
const S32 LL_VERSION_MAJOR = 2;
const S32 LL_VERSION_MINOR = 7;
const S32 LL_VERSION_PATCH = 6;
const S32 LL_VERSION_MAJOR = 3;
const S32 LL_VERSION_MINOR = 0;
const S32 LL_VERSION_PATCH = 5;
const S32 LL_VERSION_BUILD = 0;
const char * const LL_CHANNEL = "Second Life Developer";

View File

@ -37,12 +37,7 @@
LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded) :
LLQueuedThread(name, threaded)
{
mDeleteMutex = new LLMutex(NULL);
if(!mLocalAPRFilePoolp)
{
mLocalAPRFilePoolp = new LLVolatileAPRPool() ;
}
mDeleteMutex = new LLMutex;
}
LLWorkerThread::~LLWorkerThread()
@ -204,7 +199,6 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na
mWorkerClassName(name),
mRequestHandle(LLWorkerThread::nullHandle()),
mRequestPriority(LLWorkerThread::PRIORITY_NORMAL),
mMutex(NULL),
mWorkFlags(0)
{
if (!mWorkerThread)

View File

@ -94,7 +94,6 @@ public:
private:
void deleteWorker(LLWorkerClass* workerclass); // schedule for deletion
};
//============================================================================
@ -194,7 +193,7 @@ protected:
U32 mRequestPriority; // last priority set
private:
LLMutex mMutex;
LLMutexRootPool mMutex; // Use LLMutexRootPool since this object is created and destructed by multiple threads.
LLAtomicU32 mWorkFlags;
};

View File

@ -40,6 +40,7 @@
#include <boost/scoped_ptr.hpp>
// other Linden headers
#include "../test/lltut.h"
#include "wrapllerrs.h"
struct Keyed: public LLInstanceTracker<Keyed, std::string>
{
@ -151,33 +152,81 @@ namespace tut
{
Unkeyed one, two, three;
typedef std::set<Unkeyed*> KeySet;
KeySet keys;
keys.insert(&one);
keys.insert(&two);
keys.insert(&three);
{
Unkeyed::LLInstanceTrackerScopedGuard guard;
for (Unkeyed::key_iter ki(guard.beginKeys()), kend(guard.endKeys());
ki != kend; ++ki)
{
ensure_equals("spurious key", keys.erase(*ki), 1);
}
}
ensure_equals("unreported key", keys.size(), 0);
KeySet instances;
instances.insert(&one);
instances.insert(&two);
instances.insert(&three);
{
Unkeyed::LLInstanceTrackerScopedGuard guard;
for (Unkeyed::instance_iter ii(guard.beginInstances()), iend(guard.endInstances());
ii != iend; ++ii)
for (Unkeyed::instance_iter ii(Unkeyed::beginInstances()), iend(Unkeyed::endInstances()); ii != iend; ++ii)
{
Unkeyed& ref = *ii;
ensure_equals("spurious instance", instances.erase(&ref), 1);
}
}
ensure_equals("unreported instance", instances.size(), 0);
}
template<> template<>
void object::test<5>()
{
set_test_name("delete Keyed with outstanding instance_iter");
std::string what;
Keyed* keyed = new Keyed("one");
{
WrapLL_ERRS wrapper;
Keyed::instance_iter i(Keyed::beginInstances());
try
{
delete keyed;
}
catch (const WrapLL_ERRS::FatalException& e)
{
what = e.what();
}
}
ensure(! what.empty());
}
template<> template<>
void object::test<6>()
{
set_test_name("delete Keyed with outstanding key_iter");
std::string what;
Keyed* keyed = new Keyed("one");
{
WrapLL_ERRS wrapper;
Keyed::key_iter i(Keyed::beginKeys());
try
{
delete keyed;
}
catch (const WrapLL_ERRS::FatalException& e)
{
what = e.what();
}
}
ensure(! what.empty());
}
template<> template<>
void object::test<7>()
{
set_test_name("delete Unkeyed with outstanding instance_iter");
std::string what;
Unkeyed* unkeyed = new Unkeyed;
{
WrapLL_ERRS wrapper;
Unkeyed::instance_iter i(Unkeyed::beginInstances());
try
{
delete unkeyed;
}
catch (const WrapLL_ERRS::FatalException& e)
{
what = e.what();
}
}
ensure(! what.empty());
}
} // namespace tut

View File

@ -25,35 +25,293 @@
* $/LicenseInfo$
*/
#if !LL_WINDOWS
#include <netinet/in.h>
#endif
#include "linden_common.h"
#include "../llsd.h"
#include "../llsdserialize.h"
#include "../llformat.h"
#include "../test/lltut.h"
#if LL_WINDOWS
#include <winsock2.h>
typedef U32 uint32_t;
#include <process.h>
#include <io.h>
#else
#include <unistd.h>
#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include "llprocesslauncher.h"
#endif
std::vector<U8> string_to_vector(std::string str)
#include <sstream>
/*==========================================================================*|
// Whoops, seems Linden's Boost package and the viewer are built with
// different settings of VC's /Zc:wchar_t switch! Using Boost.Filesystem
// pathname operations produces Windows link errors:
// unresolved external symbol "private: static class std::codecvt<unsigned short,
// char,int> const * & __cdecl boost::filesystem3::path::wchar_t_codecvt_facet()"
// unresolved external symbol "void __cdecl boost::filesystem3::path_traits::convert()"
// See:
// http://boost.2283326.n4.nabble.com/filesystem-v3-unicode-and-std-codecvt-linker-error-td3455549.html
// which points to:
// http://msdn.microsoft.com/en-us/library/dh8che7s%28v=VS.100%29.aspx
// As we're not trying to preserve compatibility with old Boost.Filesystem
// code, but rather writing brand-new code, use the newest available
// Filesystem API.
#define BOOST_FILESYSTEM_VERSION 3
#include "boost/filesystem.hpp"
#include "boost/filesystem/v3/fstream.hpp"
|*==========================================================================*/
#include "boost/range.hpp"
#include "boost/foreach.hpp"
#include "boost/function.hpp"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/bind.hpp"
namespace lambda = boost::lambda;
/*==========================================================================*|
// Aaaarrgh, Linden's Boost package doesn't even include Boost.Iostreams!
#include "boost/iostreams/stream.hpp"
#include "boost/iostreams/device/file_descriptor.hpp"
|*==========================================================================*/
#include "../llsd.h"
#include "../llsdserialize.h"
#include "llsdutil.h"
#include "../llformat.h"
#include "../test/lltut.h"
#include "stringize.h"
std::vector<U8> string_to_vector(const std::string& str)
{
// bc LLSD can't...
size_t len = (size_t)str.length();
std::vector<U8> v(len);
for (size_t i = 0; i < len ; i++)
{
v[i] = str[i];
}
return v;
return std::vector<U8>(str.begin(), str.end());
}
#if ! LL_WINDOWS
// We want to call strerror_r(), but alarmingly, there are two different
// variants. The one that returns int always populates the passed buffer
// (except in case of error), whereas the other one always returns a valid
// char* but might or might not populate the passed buffer. How do we know
// which one we're getting? Define adapters for each and let the compiler
// select the applicable adapter.
// strerror_r() returns char*
std::string message_from(int /*orig_errno*/, const char* /*buffer*/, const char* strerror_ret)
{
return strerror_ret;
}
// strerror_r() returns int
std::string message_from(int orig_errno, const char* buffer, int strerror_ret)
{
if (strerror_ret == 0)
{
return buffer;
}
// Here strerror_r() has set errno. Since strerror_r() has already failed,
// seems like a poor bet to call it again to diagnose its own error...
int stre_errno = errno;
if (stre_errno == ERANGE)
{
return STRINGIZE("strerror_r() can't explain errno " << orig_errno
<< " (buffer too small)");
}
if (stre_errno == EINVAL)
{
return STRINGIZE("unknown errno " << orig_errno);
}
// Here we don't even understand the errno from strerror_r()!
return STRINGIZE("strerror_r() can't explain errno " << orig_errno
<< " (error " << stre_errno << ')');
}
#endif // ! LL_WINDOWS
// boost::filesystem::temp_directory_path() isn't yet in Boost 1.45! :-(
std::string temp_directory_path()
{
#if LL_WINDOWS
char buffer[4096];
GetTempPathA(sizeof(buffer), buffer);
return buffer;
#else // LL_DARWIN, LL_LINUX
static const char* vars[] = { "TMPDIR", "TMP", "TEMP", "TEMPDIR" };
BOOST_FOREACH(const char* var, vars)
{
const char* found = getenv(var);
if (found)
return found;
}
return "/tmp";
#endif // LL_DARWIN, LL_LINUX
}
// Windows presents a kinda sorta compatibility layer. Code to the yucky
// Windows names because they're less likely than the Posix names to collide
// with any other names in this source.
#if LL_WINDOWS
#define _remove DeleteFileA
#else // ! LL_WINDOWS
#define _open open
#define _write write
#define _close close
#define _remove remove
#endif // ! LL_WINDOWS
// Create a text file with specified content "somewhere in the
// filesystem," cleaning up when it goes out of scope.
class NamedTempFile
{
public:
// Function that accepts an ostream ref and (presumably) writes stuff to
// it, e.g.:
// (lambda::_1 << "the value is " << 17 << '\n')
typedef boost::function<void(std::ostream&)> Streamer;
NamedTempFile(const std::string& ext, const std::string& content):
mPath(temp_directory_path())
{
createFile(ext, lambda::_1 << content);
}
// Disambiguate when passing string literal
NamedTempFile(const std::string& ext, const char* content):
mPath(temp_directory_path())
{
createFile(ext, lambda::_1 << content);
}
NamedTempFile(const std::string& ext, const Streamer& func):
mPath(temp_directory_path())
{
createFile(ext, func);
}
~NamedTempFile()
{
_remove(mPath.c_str());
}
std::string getName() const { return mPath; }
private:
void createFile(const std::string& ext, const Streamer& func)
{
// Silly maybe, but use 'ext' as the name prefix. Strip off a leading
// '.' if present.
int pfx_offset = ((! ext.empty()) && ext[0] == '.')? 1 : 0;
#if ! LL_WINDOWS
// Make sure mPath ends with a directory separator, if it doesn't already.
if (mPath.empty() ||
! (mPath[mPath.length() - 1] == '\\' || mPath[mPath.length() - 1] == '/'))
{
mPath.append("/");
}
// mkstemp() accepts and modifies a char* template string. Generate
// the template string, then copy to modifiable storage.
// mkstemp() requires its template string to end in six X's.
mPath += ext.substr(pfx_offset) + "XXXXXX";
// Copy to vector<char>
std::vector<char> pathtemplate(mPath.begin(), mPath.end());
// append a nul byte for classic-C semantics
pathtemplate.push_back('\0');
// std::vector promises that a pointer to the 0th element is the same
// as a pointer to a contiguous classic-C array
int fd(mkstemp(&pathtemplate[0]));
if (fd == -1)
{
// The documented errno values (http://linux.die.net/man/3/mkstemp)
// are used in a somewhat unusual way, so provide context-specific
// errors.
if (errno == EEXIST)
{
LL_ERRS("NamedTempFile") << "mkstemp(\"" << mPath
<< "\") could not create unique file " << LL_ENDL;
}
if (errno == EINVAL)
{
LL_ERRS("NamedTempFile") << "bad mkstemp() file path template '"
<< mPath << "'" << LL_ENDL;
}
// Shrug, something else
int mkst_errno = errno;
char buffer[256];
LL_ERRS("NamedTempFile") << "mkstemp(\"" << mPath << "\") failed: "
<< message_from(mkst_errno, buffer,
strerror_r(mkst_errno, buffer, sizeof(buffer)))
<< LL_ENDL;
}
// mkstemp() seems to have worked! Capture the modified filename.
// Avoid the nul byte we appended.
mPath.assign(pathtemplate.begin(), (pathtemplate.end()-1));
/*==========================================================================*|
// Define an ostream on the open fd. Tell it to close fd on destruction.
boost::iostreams::stream<boost::iostreams::file_descriptor_sink>
out(fd, boost::iostreams::close_handle);
|*==========================================================================*/
// Write desired content.
std::ostringstream out;
// Stream stuff to it.
func(out);
std::string data(out.str());
int written(_write(fd, data.c_str(), data.length()));
int closed(_close(fd));
llassert_always(written == data.length() && closed == 0);
#else // LL_WINDOWS
// GetTempFileName() is documented to require a MAX_PATH buffer.
char tempname[MAX_PATH];
// Use 'ext' as filename prefix, but skip leading '.' if any.
// The 0 param is very important: requests iterating until we get a
// unique name.
if (0 == GetTempFileNameA(mPath.c_str(), ext.c_str() + pfx_offset, 0, tempname))
{
// I always have to look up this call... :-P
LPSTR msgptr;
FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
LPSTR(&msgptr), // have to cast (char**) to (char*)
0, NULL );
LL_ERRS("NamedTempFile") << "GetTempFileName(\"" << mPath << "\", \""
<< (ext.c_str() + pfx_offset) << "\") failed: "
<< msgptr << LL_ENDL;
LocalFree(msgptr);
}
// GetTempFileName() appears to have worked! Capture the actual
// filename.
mPath = tempname;
// Open the file and stream content to it. Destructor will close.
std::ofstream out(tempname);
func(out);
#endif // LL_WINDOWS
}
void peep()
{
std::cout << "File '" << mPath << "' contains:\n";
std::ifstream reader(mPath.c_str());
std::string line;
while (std::getline(reader, line))
std::cout << line << '\n';
std::cout << "---\n";
}
std::string mPath;
};
namespace tut
{
struct sd_xml_data
@ -1494,5 +1752,223 @@ namespace tut
ensureBinaryAndNotation("map", test);
ensureBinaryAndXML("map", test);
}
}
struct TestPythonCompatible
{
TestPythonCompatible():
// Note the peculiar insertion of __FILE__ into this string. Since
// this script is being written into a platform-dependent temp
// directory, we can't locate indra/lib/python relative to
// Python's __file__. Use __FILE__ instead, navigating relative
// to this C++ source file. Use Python raw-string syntax so
// Windows pathname backslashes won't mislead Python's string
// scanner.
import_llsd("import os.path\n"
"import sys\n"
"sys.path.insert(0,\n"
" os.path.join(os.path.dirname(r'" __FILE__ "'),\n"
" os.pardir, os.pardir, 'lib', 'python'))\n"
"try:\n"
" from llbase import llsd\n"
"except ImportError:\n"
" from indra.base import llsd\n")
{}
~TestPythonCompatible() {}
std::string import_llsd;
template <typename CONTENT>
void python(const std::string& desc, const CONTENT& script, int expect=0)
{
const char* PYTHON(getenv("PYTHON"));
ensure("Set $PYTHON to the Python interpreter", PYTHON);
NamedTempFile scriptfile(".py", script);
#if LL_WINDOWS
std::string q("\"");
std::string qPYTHON(q + PYTHON + q);
std::string qscript(q + scriptfile.getName() + q);
int rc = _spawnl(_P_WAIT, PYTHON, qPYTHON.c_str(), qscript.c_str(), NULL);
if (rc == -1)
{
char buffer[256];
strerror_s(buffer, errno); // C++ can infer the buffer size! :-O
ensure(STRINGIZE("Couldn't run Python " << desc << "script: " << buffer), false);
}
else
{
ensure_equals(STRINGIZE(desc << " script terminated with rc " << rc), rc, expect);
}
#else // LL_DARWIN, LL_LINUX
LLProcessLauncher py;
py.setExecutable(PYTHON);
py.addArgument(scriptfile.getName());
ensure_equals(STRINGIZE("Couldn't launch " << desc << " script"), py.launch(), 0);
// Implementing timeout would mean messing with alarm() and
// catching SIGALRM... later maybe...
int status(0);
if (waitpid(py.getProcessID(), &status, 0) == -1)
{
int waitpid_errno(errno);
ensure_equals(STRINGIZE("Couldn't retrieve rc from " << desc << " script: "
"waitpid() errno " << waitpid_errno),
waitpid_errno, ECHILD);
}
else
{
if (WIFEXITED(status))
{
int rc(WEXITSTATUS(status));
ensure_equals(STRINGIZE(desc << " script terminated with rc " << rc),
rc, expect);
}
else if (WIFSIGNALED(status))
{
ensure(STRINGIZE(desc << " script terminated by signal " << WTERMSIG(status)),
false);
}
else
{
ensure(STRINGIZE(desc << " script produced impossible status " << status),
false);
}
}
#endif
}
};
typedef tut::test_group<TestPythonCompatible> TestPythonCompatibleGroup;
typedef TestPythonCompatibleGroup::object TestPythonCompatibleObject;
TestPythonCompatibleGroup pycompat("LLSD serialize Python compatibility");
template<> template<>
void TestPythonCompatibleObject::test<1>()
{
set_test_name("verify python()");
python("hello",
"import sys\n"
"sys.exit(17)\n",
17); // expect nonzero rc
}
template<> template<>
void TestPythonCompatibleObject::test<2>()
{
set_test_name("verify NamedTempFile");
python("platform",
"import sys\n"
"print 'Running on', sys.platform\n");
}
template<> template<>
void TestPythonCompatibleObject::test<3>()
{
set_test_name("verify sequence to Python");
LLSD cdata(LLSDArray(17)(3.14)
("This string\n"
"has several\n"
"lines."));
const char pydata[] =
"def verify(iterable):\n"
" it = iter(iterable)\n"
" assert it.next() == 17\n"
" assert abs(it.next() - 3.14) < 0.01\n"
" assert it.next() == '''\\\n"
"This string\n"
"has several\n"
"lines.'''\n"
" try:\n"
" it.next()\n"
" except StopIteration:\n"
" pass\n"
" else:\n"
" assert False, 'Too many data items'\n";
// Create a something.llsd file containing 'data' serialized to
// notation. It's important to separate with newlines because Python's
// llsd module doesn't support parsing from a file stream, only from a
// string, so we have to know how much of the file to read into a
// string.
NamedTempFile file(".llsd",
// NamedTempFile's boost::function constructor
// takes a callable. To this callable it passes the
// std::ostream with which it's writing the
// NamedTempFile. This lambda-based expression
// first calls LLSD::Serialize() with that ostream,
// then streams a newline to it, etc.
(lambda::bind(LLSDSerialize::toNotation, cdata[0], lambda::_1),
lambda::_1 << '\n',
lambda::bind(LLSDSerialize::toNotation, cdata[1], lambda::_1),
lambda::_1 << '\n',
lambda::bind(LLSDSerialize::toNotation, cdata[2], lambda::_1),
lambda::_1 << '\n'));
python("read C++ notation",
lambda::_1 <<
import_llsd <<
"def parse_each(iterable):\n"
" for item in iterable:\n"
" yield llsd.parse(item)\n" <<
pydata <<
// Don't forget raw-string syntax for Windows pathnames.
"verify(parse_each(open(r'" << file.getName() << "')))\n");
}
template<> template<>
void TestPythonCompatibleObject::test<4>()
{
set_test_name("verify sequence from Python");
// Create an empty data file. This is just a placeholder for our
// script to write into. Create it to establish a unique name that
// we know.
NamedTempFile file(".llsd", "");
python("write Python notation",
lambda::_1 <<
"from __future__ import with_statement\n" <<
import_llsd <<
"DATA = [\n"
" 17,\n"
" 3.14,\n"
" '''\\\n"
"This string\n"
"has several\n"
"lines.''',\n"
"]\n"
// Don't forget raw-string syntax for Windows pathnames.
// N.B. Using 'print' implicitly adds newlines.
"with open(r'" << file.getName() << "', 'w') as f:\n"
" for item in DATA:\n"
" print >>f, llsd.format_notation(item)\n");
std::ifstream inf(file.getName().c_str());
LLSD item;
// Notice that we're not doing anything special to parse out the
// newlines: LLSDSerialize::fromNotation ignores them. While it would
// seem they're not strictly necessary, going in this direction, we
// want to ensure that notation-separated-by-newlines works in both
// directions -- since in practice, a given file might be read by
// either language.
ensure_equals("Failed to read LLSD::Integer from Python",
LLSDSerialize::fromNotation(item, inf, LLSDSerialize::SIZE_UNLIMITED),
1);
ensure_equals(item.asInteger(), 17);
ensure_equals("Failed to read LLSD::Real from Python",
LLSDSerialize::fromNotation(item, inf, LLSDSerialize::SIZE_UNLIMITED),
1);
ensure_approximately_equals("Bad LLSD::Real value from Python",
item.asReal(), 3.14, 7); // 7 bits ~= 0.01
ensure_equals("Failed to read LLSD::String from Python",
LLSDSerialize::fromNotation(item, inf, LLSDSerialize::SIZE_UNLIMITED),
1);
ensure_equals(item.asString(),
"This string\n"
"has several\n"
"lines.");
}
}

View File

@ -624,6 +624,14 @@ namespace tut
subcount = LLStringUtil::format(s, fmt_map);
ensure_equals("LLStringUtil::format: Assorted Test2 result", s, "?Am I not a long string?short[A]bbbaaaba[A]");
ensure_equals("LLStringUtil::format: Assorted Test2 result count", 9, subcount);
// Test on nested brackets
std::string srcs6 = "[[TRICK1]][[A]][[B]][[AAA]][[BBB]][[TRICK2]][[KEYLONGER]][[KEYSHORTER]]?[[DELETE]]";
s = srcs6;
subcount = LLStringUtil::format(s, fmt_map);
ensure_equals("LLStringUtil::format: Assorted Test2 result", s, "[[A]][a][b][aaa][bbb][[A]][short][Am I not a long string?]?[]");
ensure_equals("LLStringUtil::format: Assorted Test2 result count", 9, subcount);
// Test an assorted substitution
std::string srcs8 = "foo[DELETE]bar?";

View File

@ -0,0 +1,19 @@
#!/usr/bin/python
"""\
@file setpython.py
@author Nat Goodspeed
@date 2011-07-13
@brief Set PYTHON environment variable for tests that care.
$LicenseInfo:firstyear=2011&license=viewerlgpl$
Copyright (c) 2011, Linden Research, Inc.
$/LicenseInfo$
"""
import os
import sys
import subprocess
if __name__ == "__main__":
os.environ["PYTHON"] = sys.executable
sys.exit(subprocess.call(sys.argv[1:]))

View File

@ -31,10 +31,12 @@
#include "llcrashlogger.h"
#include "linden_common.h"
#include "llstring.h"
#include "indra_constants.h" // CRASH_BEHAVIOR_ASK, CRASH_SETTING_NAME
#include "indra_constants.h" // CRASH_BEHAVIOR_...
#include "llerror.h"
#include "llerrorcontrol.h"
#include "lltimer.h"
#include "lldir.h"
#include "llfile.h"
#include "llsdserialize.h"
#include "lliopipe.h"
#include "llpumpio.h"
@ -54,7 +56,7 @@ public:
virtual void error(U32 status, const std::string& reason)
{
gBreak = true;
gBreak = true;
}
virtual void result(const LLSD& content)
@ -64,21 +66,8 @@ public:
}
};
bool LLCrashLoggerText::mainLoop()
{
std::cout << "Entering main loop" << std::endl;
sendCrashLogs();
return true;
}
void LLCrashLoggerText::updateApplication(const std::string& message)
{
LLCrashLogger::updateApplication(message);
std::cout << message << std::endl;
}
LLCrashLogger::LLCrashLogger() :
mCrashBehavior(CRASH_BEHAVIOR_ASK),
mCrashBehavior(CRASH_BEHAVIOR_ALWAYS_SEND),
mCrashInPreviousExec(false),
mCrashSettings("CrashSettings"),
mSentCrashLogs(false),
@ -281,26 +270,48 @@ LLSD LLCrashLogger::constructPostData()
return mCrashInfo;
}
const char* const CRASH_SETTINGS_FILE = "settings_crash_behavior.xml";
S32 LLCrashLogger::loadCrashBehaviorSetting()
{
// First check user_settings (in the user's home dir)
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
if (! mCrashSettings.loadFromFile(filename))
{
// Next check app_settings (in the SL program dir)
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, CRASH_SETTINGS_FILE);
mCrashSettings.loadFromFile(filename);
}
mCrashSettings.loadFromFile(filename);
S32 value = mCrashSettings.getS32(CRASH_BEHAVIOR_SETTING);
if (value < CRASH_BEHAVIOR_ASK || CRASH_BEHAVIOR_NEVER_SEND < value) return CRASH_BEHAVIOR_ASK;
// If we didn't load any files above, this will return the default
S32 value = mCrashSettings.getS32("CrashSubmitBehavior");
return value;
// Whatever value we got, make sure it's valid
switch (value)
{
case CRASH_BEHAVIOR_NEVER_SEND:
return CRASH_BEHAVIOR_NEVER_SEND;
case CRASH_BEHAVIOR_ALWAYS_SEND:
return CRASH_BEHAVIOR_ALWAYS_SEND;
}
return CRASH_BEHAVIOR_ASK;
}
bool LLCrashLogger::saveCrashBehaviorSetting(S32 crash_behavior)
{
if (crash_behavior != CRASH_BEHAVIOR_ASK && crash_behavior != CRASH_BEHAVIOR_ALWAYS_SEND) return false;
switch (crash_behavior)
{
case CRASH_BEHAVIOR_ASK:
case CRASH_BEHAVIOR_NEVER_SEND:
case CRASH_BEHAVIOR_ALWAYS_SEND:
break;
default:
return false;
}
mCrashSettings.setS32(CRASH_BEHAVIOR_SETTING, crash_behavior);
mCrashSettings.setS32("CrashSubmitBehavior", crash_behavior);
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
mCrashSettings.saveToFile(filename, FALSE);
return true;
@ -309,14 +320,13 @@ bool LLCrashLogger::saveCrashBehaviorSetting(S32 crash_behavior)
bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg, int retries, int timeout)
{
gBreak = false;
std::string status_message;
for(int i = 0; i < retries; ++i)
{
status_message = llformat("%s, try %d...", msg.c_str(), i+1);
updateApplication(llformat("%s, try %d...", msg.c_str(), i+1));
LLHTTPClient::post(host, data, new LLCrashLoggerResponder(), timeout);
while(!gBreak)
{
updateApplication(status_message);
updateApplication(); // No new message, just pump the IO
}
if(gSent)
{
@ -336,7 +346,7 @@ bool LLCrashLogger::sendCrashLogs()
updateApplication("Sending reports...");
std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
"SecondLifeCrashReport");
"SecondLifeCrashReport");
std::string report_file = dump_path + ".log";
std::ofstream out_file(report_file.c_str());
@ -365,23 +375,37 @@ void LLCrashLogger::updateApplication(const std::string& message)
{
gServicePump->pump();
gServicePump->callback();
if (!message.empty()) llinfos << message << llendl;
}
bool LLCrashLogger::init()
{
LLCurl::initClass();
LLCurl::initClass(false);
// We assume that all the logs we're looking for reside on the current drive
gDirUtilp->initAppDirs("SecondLife");
LLError::initForApplication(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
// Default to the product name "Second Life" (this is overridden by the -name argument)
mProductName = "Second Life";
mCrashSettings.declareS32(CRASH_BEHAVIOR_SETTING, CRASH_BEHAVIOR_ASK, "Controls behavior when viewer crashes "
"(0 = ask before sending crash report, 1 = always send crash report, 2 = never send crash report)");
llinfos << "Loading crash behavior setting" << llendl;
mCrashBehavior = loadCrashBehaviorSetting();
// Rename current log file to ".old"
std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "crashreport.log.old");
std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "crashreport.log");
LLFile::rename(log_file.c_str(), old_log_file.c_str());
// Set the log file to crashreport.log
LLError::logToFile(log_file);
mCrashSettings.declareS32("CrashSubmitBehavior", CRASH_BEHAVIOR_ALWAYS_SEND,
"Controls behavior when viewer crashes "
"(0 = ask before sending crash report, "
"1 = always send crash report, "
"2 = never send crash report)");
// llinfos << "Loading crash behavior setting" << llendl;
// mCrashBehavior = loadCrashBehaviorSetting();
// If user doesn't want to send, bail out
if (mCrashBehavior == CRASH_BEHAVIOR_NEVER_SEND)
@ -390,14 +414,14 @@ bool LLCrashLogger::init()
return false;
}
gServicePump = new LLPumpIO(gAPRPoolp);
gServicePump->prime(gAPRPoolp);
gServicePump = new LLPumpIO;
LLHTTPClient::setPump(*gServicePump);
//If we've opened the crash logger, assume we can delete the marker file if it exists
//If we've opened the crash logger, assume we can delete the marker file if it exists
if( gDirUtilp )
{
std::string marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.exec_marker");
std::string marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
"SecondLife.exec_marker");
LLAPRFile::remove( marker_file );
}

View File

@ -66,15 +66,4 @@ protected:
bool mSentCrashLogs;
};
class LLCrashLoggerText : public LLCrashLogger
{
public:
LLCrashLoggerText(void) {}
~LLCrashLoggerText(void) {}
virtual bool mainLoop();
virtual void updateApplication(const std::string& message = LLStringUtil::null);
};
#endif //LLCRASHLOGGER_H

View File

@ -39,6 +39,7 @@
#include "llimagepng.h"
#include "llimagedxt.h"
#include "llimageworker.h"
#include "llmemory.h"
//---------------------------------------------------------------------------
// LLImage
@ -47,11 +48,14 @@
//static
std::string LLImage::sLastErrorMessage;
LLMutex* LLImage::sMutex = NULL;
LLPrivateMemoryPool* LLImageBase::sPrivatePoolp = NULL ;
//static
void LLImage::initClass()
{
sMutex = new LLMutex(NULL);
sMutex = new LLMutex;
LLImageBase::createPrivatePool() ;
}
//static
@ -59,6 +63,8 @@ void LLImage::cleanupClass()
{
delete sMutex;
sMutex = NULL;
LLImageBase::destroyPrivatePool() ;
}
//static
@ -97,6 +103,25 @@ LLImageBase::~LLImageBase()
deleteData(); // virtual
}
//static
void LLImageBase::createPrivatePool()
{
if(!sPrivatePoolp)
{
sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(LLPrivateMemoryPool::STATIC_THREADED) ;
}
}
//static
void LLImageBase::destroyPrivatePool()
{
if(sPrivatePoolp)
{
LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp) ;
sPrivatePoolp = NULL ;
}
}
// virtual
void LLImageBase::dump()
{
@ -130,7 +155,7 @@ void LLImageBase::sanityCheck()
// virtual
void LLImageBase::deleteData()
{
delete[] mData;
FREE_MEM(sPrivatePoolp, mData) ;
mData = NULL;
mDataSize = 0;
}
@ -167,7 +192,7 @@ U8* LLImageBase::allocateData(S32 size)
{
deleteData(); // virtual
mBadBufferAllocation = false ;
mData = new U8[size];
mData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size);
if (!mData)
{
llwarns << "allocate image data: " << size << llendl;
@ -185,7 +210,7 @@ U8* LLImageBase::allocateData(S32 size)
U8* LLImageBase::reallocateData(S32 size)
{
LLMemType mt1(mMemType);
U8 *new_datap = new U8[size];
U8 *new_datap = (U8*)ALLOCATE_MEM(sPrivatePoolp, size);
if (!new_datap)
{
llwarns << "Out of memory in LLImageBase::reallocateData" << llendl;
@ -195,7 +220,7 @@ U8* LLImageBase::reallocateData(S32 size)
{
S32 bytes = llmin(mDataSize, size);
memcpy(new_datap, mData, bytes); /* Flawfinder: ignore */
delete[] mData;
FREE_MEM(sPrivatePoolp, mData) ;
}
mData = new_datap;
mDataSize = size;
@ -341,6 +366,7 @@ BOOL LLImageRaw::resize(U16 width, U16 height, S8 components)
return TRUE;
}
#if 0
U8 * LLImageRaw::getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const
{
LLMemType mt1(mMemType);
@ -361,6 +387,7 @@ U8 * LLImageRaw::getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const
}
return data;
}
#endif
BOOL LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
const U8 *data, U32 stride, BOOL reverse_y)
@ -830,6 +857,7 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
}
}
#if 0
//scale down image by not blending a pixel with its neighbors.
BOOL LLImageRaw::scaleDownWithoutBlending( S32 new_width, S32 new_height)
{
@ -853,7 +881,7 @@ BOOL LLImageRaw::scaleDownWithoutBlending( S32 new_width, S32 new_height)
ratio_x -= 1.0f ;
ratio_y -= 1.0f ;
U8* new_data = new U8[new_data_size] ;
U8* new_data = allocateMemory(new_data_size) ;
llassert_always(new_data != NULL) ;
U8* old_data = getData() ;
@ -875,6 +903,7 @@ BOOL LLImageRaw::scaleDownWithoutBlending( S32 new_width, S32 new_height)
return TRUE ;
}
#endif
BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
{
@ -1506,6 +1535,7 @@ void LLImageFormatted::setData(U8 *data, S32 size)
{
deleteData();
setDataAndSize(data, size); // Access private LLImageBase members
sGlobalFormattedMemory += getDataSize();
}
}
@ -1524,7 +1554,7 @@ void LLImageFormatted::appendData(U8 *data, S32 size)
S32 newsize = cursize + size;
reallocateData(newsize);
memcpy(getData() + cursize, data, size);
delete[] data;
FREE_MEM(LLImageBase::getPrivatePool(), data);
}
}
}
@ -1536,8 +1566,7 @@ BOOL LLImageFormatted::load(const std::string &filename)
resetLastError();
S32 file_size = 0;
LLAPRFile infile ;
infile.open(filename, LL_APR_RB, NULL, &file_size);
LLAPRFile infile(filename, LL_APR_RB, &file_size);
apr_file_t* apr_file = infile.getFileHandle();
if (!apr_file)
{
@ -1572,8 +1601,7 @@ BOOL LLImageFormatted::save(const std::string &filename)
{
resetLastError();
LLAPRFile outfile ;
outfile.open(filename, LL_APR_WB);
LLAPRFile outfile(filename, LL_APR_WB);
if (!outfile.getFileHandle())
{
setLastError("Unable to open file for writing", filename);

View File

@ -29,7 +29,6 @@
#include "lluuid.h"
#include "llstring.h"
//#include "llmemory.h"
#include "llthread.h"
#include "llmemtype.h"
@ -69,6 +68,7 @@ const S32 MAX_IMG_PACKET_SIZE = 1000;
class LLImageFormatted;
class LLImageRaw;
class LLColor4U;
class LLPrivateMemoryPool;
typedef enum e_image_codec
{
@ -140,7 +140,7 @@ public:
protected:
// special accessor to allow direct setting of mData and mDataSize by LLImageFormatted
void setDataAndSize(U8 *data, S32 size) { mData = data; mDataSize = size; }
void setDataAndSize(U8 *data, S32 size) { mData = data; mDataSize = size; }
public:
static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels);
@ -151,6 +151,10 @@ public:
static EImageCodec getCodecFromExtension(const std::string& exten);
static void createPrivatePool() ;
static void destroyPrivatePool() ;
static LLPrivateMemoryPool* getPrivatePool() {return sPrivatePoolp;}
private:
U8 *mData;
S32 mDataSize;
@ -162,6 +166,8 @@ private:
bool mBadBufferAllocation ;
bool mAllowOverSize ;
static LLPrivateMemoryPool* sPrivatePoolp ;
public:
LLMemType::DeclareMemType& mMemType; // debug
};
@ -185,7 +191,7 @@ public:
BOOL resize(U16 width, U16 height, S8 components);
U8 * getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const;
//U8 * getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const;
BOOL setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
const U8 *data, U32 stride = 0, BOOL reverse_y = FALSE);
@ -197,7 +203,7 @@ public:
void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE);
BOOL scale( S32 new_width, S32 new_height, BOOL scale_image = TRUE );
BOOL scaleDownWithoutBlending( S32 new_width, S32 new_height) ;
//BOOL scaleDownWithoutBlending( S32 new_width, S32 new_height) ;
// Fill the buffer with a constant color
void fill( const LLColor4U& color );

View File

@ -40,7 +40,7 @@ bool LLImageDimensionsInfo::load(const std::string& src_filename,U32 codec)
mSrcFilename = src_filename;
S32 file_size = 0;
apr_status_t s = mInfile.open(src_filename, LL_APR_RB, NULL, &file_size);
apr_status_t s = mInfile.open(src_filename, LL_APR_RB, LLAPRFile::long_lived, &file_size);
if (s != APR_SUCCESS)
{

View File

@ -429,7 +429,7 @@ bool LLImageDXT::convertToDXR()
S32 nmips = calcNumMips(width,height);
S32 total_bytes = getDataSize();
U8* olddata = getData();
U8* newdata = new U8[total_bytes];
U8* newdata = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), total_bytes);
if (!newdata)
{
llerrs << "Out of memory in LLImageDXT::convertToDXR()" << llendl;

View File

@ -370,8 +370,7 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename)
resetLastError();
S32 file_size = 0;
LLAPRFile infile ;
infile.open(filename, LL_APR_RB, NULL, &file_size);
LLAPRFile infile(filename, LL_APR_RB, &file_size);
apr_file_t* apr_file = infile.getFileHandle() ;
if (!apr_file)
{
@ -385,14 +384,14 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename)
}
else
{
U8 *data = new U8[file_size];
U8 *data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), file_size);
apr_size_t bytes_read = file_size;
apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
infile.close() ;
if (s != APR_SUCCESS || (S32)bytes_read != file_size)
{
delete[] data;
FREE_MEM(LLImageBase::getPrivatePool(), data);
setLastError("Unable to read entire file");
res = FALSE;
}

View File

@ -35,20 +35,18 @@
LLImageDecodeThread::LLImageDecodeThread(bool threaded)
: LLQueuedThread("imagedecode", threaded)
{
mCreationMutex = new LLMutex(getAPRPool());
}
//virtual
LLImageDecodeThread::~LLImageDecodeThread()
{
delete mCreationMutex ;
}
// MAIN THREAD
// virtual
S32 LLImageDecodeThread::update(U32 max_time_ms)
{
LLMutexLock lock(mCreationMutex);
LLMutexLock lock(&mCreationMutex);
for (creation_list_t::iterator iter = mCreationList.begin();
iter != mCreationList.end(); ++iter)
{
@ -71,7 +69,7 @@ S32 LLImageDecodeThread::update(U32 max_time_ms)
LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image,
U32 priority, S32 discard, BOOL needs_aux, Responder* responder)
{
LLMutexLock lock(mCreationMutex);
LLMutexLock lock(&mCreationMutex);
handle_t handle = generateHandle();
mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder));
return handle;
@ -81,7 +79,7 @@ LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted*
// Returns the size of the mutex guarded list as an indication of sanity
S32 LLImageDecodeThread::tut_size()
{
LLMutexLock lock(mCreationMutex);
LLMutexLock lock(&mCreationMutex);
S32 res = mCreationList.size();
return res;
}

View File

@ -98,7 +98,7 @@ private:
};
typedef std::list<creation_info> creation_list_t;
creation_list_t mCreationList;
LLMutex* mCreationMutex;
LLMutex mCreationMutex;
};
#endif

View File

@ -62,14 +62,14 @@ add_library (llinventory ${llinventory_SOURCE_FILES})
#add unit tests
if (LL_TESTS)
INCLUDE(LLAddBuildTest)
SET(llinventory_TEST_SOURCE_FILES
# no real unit tests yet!
)
LL_ADD_PROJECT_UNIT_TESTS(llinventory "${llinventory_TEST_SOURCE_FILES}")
INCLUDE(LLAddBuildTest)
SET(llinventory_TEST_SOURCE_FILES
# no real unit tests yet!
)
LL_ADD_PROJECT_UNIT_TESTS(llinventory "${llinventory_TEST_SOURCE_FILES}")
#set(TEST_DEBUG on)
set(test_libs llinventory ${LLMESSAGE_LIBRARIES} ${LLVFS_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
LL_ADD_INTEGRATION_TEST(inventorymisc "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llparcel "" "${test_libs}")
#set(TEST_DEBUG on)
set(test_libs llinventory ${LLMESSAGE_LIBRARIES} ${LLVFS_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
LL_ADD_INTEGRATION_TEST(inventorymisc "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llparcel "" "${test_libs}")
endif (LL_TESTS)

View File

@ -1034,8 +1034,11 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
sd[INV_CREATION_DATE_LABEL] = (S32) mCreationDate;
}
LLFastTimer::DeclareTimer FTM_INVENTORY_SD_DESERIALIZE("Inventory SD Deserialize");
bool LLInventoryItem::fromLLSD(const LLSD& sd)
{
LLFastTimer _(FTM_INVENTORY_SD_DESERIALIZE);
mInventoryType = LLInventoryType::IT_NONE;
mAssetUUID.setNull();
std::string w;

View File

@ -226,6 +226,11 @@ void LLParcel::init(const LLUUID &owner_id,
setPreviousOwnerID(LLUUID::null);
setPreviouslyGroupOwned(FALSE);
setSeeAVs(TRUE);
setAllowGroupAVSounds(TRUE);
setAllowAnyAVSounds(TRUE);
setHaveNewParcelLimitData(FALSE);
}
void LLParcel::overrideOwner(const LLUUID& owner_id, BOOL is_group_owned)
@ -702,7 +707,9 @@ void LLParcel::packMessage(LLSD& msg)
msg["user_location"] = ll_sd_from_vector3(mUserLocation);
msg["user_look_at"] = ll_sd_from_vector3(mUserLookAt);
msg["landing_type"] = (U8)mLandingType;
msg["see_avs"] = (LLSD::Boolean) getSeeAVs();
msg["group_av_sounds"] = (LLSD::Boolean) getAllowGroupAVSounds();
msg["any_av_sounds"] = (LLSD::Boolean) getAllowAnyAVSounds();
}
@ -721,6 +728,24 @@ void LLParcel::unpackMessage(LLMessageSystem* msg)
msg->getStringFast( _PREHASH_ParcelData,_PREHASH_MediaURL, buffer );
setMediaURL(buffer);
BOOL see_avs = TRUE; // All default to true for legacy server behavior
BOOL any_av_sounds = TRUE;
BOOL group_av_sounds = TRUE;
bool have_new_parcel_limit_data = (msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_SeeAVs) > 0); // New version of server should send all 3 of these values
have_new_parcel_limit_data &= (msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_AnyAVSounds) > 0);
have_new_parcel_limit_data &= (msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_GroupAVSounds) > 0);
if (have_new_parcel_limit_data)
{
msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_SeeAVs, see_avs);
msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_AnyAVSounds, any_av_sounds);
msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_GroupAVSounds, group_av_sounds);
}
setSeeAVs((bool) see_avs);
setAllowAnyAVSounds((bool) any_av_sounds);
setAllowGroupAVSounds((bool) group_av_sounds);
setHaveNewParcelLimitData(have_new_parcel_limit_data);
// non-optimized version
msg->getU8 ( "ParcelData", "MediaAutoScale", mMediaAutoScale );

View File

@ -75,7 +75,7 @@ const U8 PARCEL_AUCTION = 0x05;
// unused 0x06
// unused 0x07
// flag, unused 0x08
// flag, unused 0x10
const U8 PARCEL_HIDDENAVS = 0x10; // avatars not visible outside of parcel. Used for 'see avs' feature, but must be off for compatibility
const U8 PARCEL_SOUND_LOCAL = 0x20;
const U8 PARCEL_WEST_LINE = 0x40; // flag, property line on west edge
const U8 PARCEL_SOUTH_LINE = 0x80; // flag, property line on south edge
@ -130,6 +130,12 @@ class LLSD;
class LLAccessEntry
{
public:
LLAccessEntry()
: mID(),
mTime(0),
mFlags(0)
{}
LLUUID mID; // Agent ID
S32 mTime; // Time (unix seconds) when entry expires
U32 mFlags; // Not used - currently should always be zero
@ -265,6 +271,8 @@ public:
void setUserLocation(const LLVector3& pos) { mUserLocation = pos; }
void setUserLookAt(const LLVector3& rot) { mUserLookAt = rot; }
void setLandingType(const ELandingType type) { mLandingType = type; }
void setSeeAVs(BOOL see_avs) { mSeeAVs = see_avs; }
void setHaveNewParcelLimitData(bool have_new_parcel_data) { mHaveNewParcelLimitData = have_new_parcel_data; } // Remove this once hidden AV feature is fully available grid-wide
void setAuctionID(U32 auction_id) { mAuctionID = auction_id;}
@ -291,6 +299,8 @@ public:
void setDenyAnonymous(BOOL b) { setParcelFlag(PF_DENY_ANONYMOUS, b); }
void setDenyAgeUnverified(BOOL b) { setParcelFlag(PF_DENY_AGEUNVERIFIED, b); }
void setRestrictPushObject(BOOL b) { setParcelFlag(PF_RESTRICT_PUSHOBJECT, b); }
void setAllowGroupAVSounds(BOOL b) { mAllowGroupAVSounds = b; }
void setAllowAnyAVSounds(BOOL b) { mAllowAnyAVSounds = b; }
void setDrawDistance(F32 dist) { mDrawDistance = dist; }
void setSalePrice(S32 price) { mSalePrice = price; }
@ -367,6 +377,8 @@ public:
const LLVector3& getUserLocation() const { return mUserLocation; }
const LLVector3& getUserLookAt() const { return mUserLookAt; }
ELandingType getLandingType() const { return mLandingType; }
BOOL getSeeAVs() const { return mSeeAVs; }
BOOL getHaveNewParcelLimitData() const { return mHaveNewParcelLimitData; }
// User-specified snapshot
const LLUUID& getSnapshotID() const { return mSnapshotID; }
@ -496,6 +508,9 @@ public:
BOOL getRegionDenyAgeUnverifiedOverride() const
{ return mRegionDenyAgeUnverifiedOverride; }
BOOL getAllowGroupAVSounds() const { return mAllowGroupAVSounds; }
BOOL getAllowAnyAVSounds() const { return mAllowAnyAVSounds; }
F32 getDrawDistance() const { return mDrawDistance; }
S32 getSalePrice() const { return mSalePrice; }
time_t getClaimDate() const { return mClaimDate; }
@ -606,6 +621,8 @@ protected:
LLVector3 mUserLocation;
LLVector3 mUserLookAt;
ELandingType mLandingType;
BOOL mSeeAVs; // Avatars on this parcel are visible from outside it
BOOL mHaveNewParcelLimitData; // Remove once hidden AV feature is grid-wide
LLTimer mSaleTimerExpires;
LLTimer mMediaResetTimer;
@ -661,6 +678,8 @@ protected:
BOOL mRegionPushOverride;
BOOL mRegionDenyAnonymousOverride;
BOOL mRegionDenyAgeUnverifiedOverride;
BOOL mAllowGroupAVSounds;
BOOL mAllowAnyAVSounds;
ParcelQuota mQuota;

View File

@ -126,5 +126,7 @@ const S32 PARCEL_DETAILS_DESC = 1;
const S32 PARCEL_DETAILS_OWNER = 2;
const S32 PARCEL_DETAILS_GROUP = 3;
const S32 PARCEL_DETAILS_AREA = 4;
const S32 PARCEL_DETAILS_ID = 5;
const S32 PARCEL_DETAILS_SEE_AVATARS = 6;
#endif

View File

@ -30,7 +30,7 @@ set(llkdu_SOURCE_FILES
set(llkdu_HEADER_FILES
CMakeLists.txt
llimagej2ckdu.h
llkdumem.h
)

View File

@ -12,6 +12,8 @@ include_directories(
set(llmath_SOURCE_FILES
llbbox.cpp
llbboxlocal.cpp
llcalc.cpp
llcalcparser.cpp
llcamera.cpp
llcoordframe.cpp
llline.cpp
@ -46,6 +48,8 @@ set(llmath_HEADER_FILES
coordframe.h
llbbox.h
llbboxlocal.h
llcalc.h
llcalcparser.h
llcamera.h
llcoord.h
llcoordframe.h

162
indra/llmath/llcalc.cpp Normal file
View File

@ -0,0 +1,162 @@
/*
* LLCalc.cpp
* Copyright 2008 Aimee Walton.
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2008, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*
*/
#include "linden_common.h"
#include "llcalc.h"
#include "llcalcparser.h"
#include "llmath.h"
// Variable names for use in the build floater
const char* LLCalc::X_POS = "PX";
const char* LLCalc::Y_POS = "PY";
const char* LLCalc::Z_POS = "PZ";
const char* LLCalc::X_SCALE = "SX";
const char* LLCalc::Y_SCALE = "SY";
const char* LLCalc::Z_SCALE = "SZ";
const char* LLCalc::X_ROT = "RX";
const char* LLCalc::Y_ROT = "RY";
const char* LLCalc::Z_ROT = "RZ";
const char* LLCalc::HOLLOW = "HLW";
const char* LLCalc::CUT_BEGIN = "CB";
const char* LLCalc::CUT_END = "CE";
const char* LLCalc::PATH_BEGIN = "PB";
const char* LLCalc::PATH_END = "PE";
const char* LLCalc::TWIST_BEGIN = "TB";
const char* LLCalc::TWIST_END = "TE";
const char* LLCalc::X_SHEAR = "SHX";
const char* LLCalc::Y_SHEAR = "SHY";
const char* LLCalc::X_TAPER = "TPX";
const char* LLCalc::Y_TAPER = "TPY";
const char* LLCalc::RADIUS_OFFSET = "ROF";
const char* LLCalc::REVOLUTIONS = "REV";
const char* LLCalc::SKEW = "SKW";
const char* LLCalc::X_HOLE = "HLX";
const char* LLCalc::Y_HOLE = "HLY";
const char* LLCalc::TEX_U_SCALE = "TSU";
const char* LLCalc::TEX_V_SCALE = "TSV";
const char* LLCalc::TEX_U_OFFSET = "TOU";
const char* LLCalc::TEX_V_OFFSET = "TOV";
const char* LLCalc::TEX_ROTATION = "TROT";
const char* LLCalc::TEX_TRANSPARENCY = "TRNS";
const char* LLCalc::TEX_GLOW = "GLOW";
LLCalc* LLCalc::sInstance = NULL;
LLCalc::LLCalc() : mLastErrorPos(0)
{
// Init table of constants
mConstants["PI"] = F_PI;
mConstants["TWO_PI"] = F_TWO_PI;
mConstants["PI_BY_TWO"] = F_PI_BY_TWO;
mConstants["SQRT_TWO_PI"] = F_SQRT_TWO_PI;
mConstants["SQRT2"] = F_SQRT2;
mConstants["SQRT3"] = F_SQRT3;
mConstants["DEG_TO_RAD"] = DEG_TO_RAD;
mConstants["RAD_TO_DEG"] = RAD_TO_DEG;
mConstants["GRAVITY"] = GRAVITY;
}
LLCalc::~LLCalc()
{
}
//static
void LLCalc::cleanUp()
{
delete sInstance;
sInstance = NULL;
}
//static
LLCalc* LLCalc::getInstance()
{
if (!sInstance) sInstance = new LLCalc();
return sInstance;
}
void LLCalc::setVar(const std::string& name, const F32& value)
{
mVariables[name] = value;
}
void LLCalc::clearVar(const std::string& name)
{
mVariables.erase(name);
}
void LLCalc::clearAllVariables()
{
mVariables.clear();
}
/*
void LLCalc::updateVariables(LLSD& vars)
{
LLSD::map_iterator cIt = vars.beginMap();
for(; cIt != vars.endMap(); cIt++)
{
setVar(cIt->first, (F32)(LLSD::Real)cIt->second);
}
}
*/
bool LLCalc::evalString(const std::string& expression, F32& result)
{
std::string expr_upper = expression;
LLStringUtil::toUpper(expr_upper);
LLCalcParser calc(result, &mConstants, &mVariables);
mLastErrorPos = 0;
std::string::iterator start = expr_upper.begin();
parse_info<std::string::iterator> info;
try
{
info = parse(start, expr_upper.end(), calc, space_p);
lldebugs << "Math expression: " << expression << " = " << result << llendl;
}
catch(parser_error<std::string, std::string::iterator> &e)
{
mLastErrorPos = e.where - expr_upper.begin();
llinfos << "Calc parser exception: " << e.descriptor << " at " << mLastErrorPos << " in expression: " << expression << llendl;
return false;
}
if (!info.full)
{
mLastErrorPos = info.stop - expr_upper.begin();
llinfos << "Unhandled syntax error at " << mLastErrorPos << " in expression: " << expression << llendl;
return false;
}
return true;
}

100
indra/llmath/llcalc.h Normal file
View File

@ -0,0 +1,100 @@
/*
* LLCalc.h
* Copyright 2008 Aimee Walton.
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2008, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*
*/
#ifndef LL_CALC_H
#define LL_CALC_H
#include <map>
#include <string>
class LLCalc
{
public:
LLCalc();
~LLCalc();
// Variable name constants
static const char* X_POS;
static const char* Y_POS;
static const char* Z_POS;
static const char* X_SCALE;
static const char* Y_SCALE;
static const char* Z_SCALE;
static const char* X_ROT;
static const char* Y_ROT;
static const char* Z_ROT;
static const char* HOLLOW;
static const char* CUT_BEGIN;
static const char* CUT_END;
static const char* PATH_BEGIN;
static const char* PATH_END;
static const char* TWIST_BEGIN;
static const char* TWIST_END;
static const char* X_SHEAR;
static const char* Y_SHEAR;
static const char* X_TAPER;
static const char* Y_TAPER;
static const char* RADIUS_OFFSET;
static const char* REVOLUTIONS;
static const char* SKEW;
static const char* X_HOLE;
static const char* Y_HOLE;
static const char* TEX_U_SCALE;
static const char* TEX_V_SCALE;
static const char* TEX_U_OFFSET;
static const char* TEX_V_OFFSET;
static const char* TEX_ROTATION;
static const char* TEX_TRANSPARENCY;
static const char* TEX_GLOW;
void setVar(const std::string& name, const F32& value);
void clearVar(const std::string& name);
void clearAllVariables();
// void updateVariables(LLSD& vars);
bool evalString(const std::string& expression, F32& result);
std::string::size_type getLastErrorPos() { return mLastErrorPos; }
static LLCalc* getInstance();
static void cleanUp();
typedef std::map<std::string, F32> calc_map_t;
private:
std::string::size_type mLastErrorPos;
calc_map_t mConstants;
calc_map_t mVariables;
// *TODO: Add support for storing user defined variables, and stored functions.
// Will need UI work, and a means to save them between sessions.
// calc_map_t mUserVariables;
// "There shall be only one"
static LLCalc* sInstance;
};
#endif // LL_CALC_H

View File

@ -0,0 +1,63 @@
/*
* LLCalcParser.cpp
* Copyright 2008 Aimee Walton.
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2008, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*
*/
#include "linden_common.h"
#include "llcalcparser.h"
using namespace boost::spirit::classic;
F32 LLCalcParser::lookup(const std::string::iterator& start, const std::string::iterator& end) const
{
LLCalc::calc_map_t::iterator iter;
std::string name(start, end);
if (mConstants)
{
iter = mConstants->find(name);
if (iter != mConstants->end())
{
return (*iter).second;
}
}
else
{
// This should never happen!
throw_(end, std::string("Missing constants table"));
}
if (mVariables)
{
iter = mVariables->find(name);
if (iter != mVariables->end())
{
return (*iter).second;
}
}
throw_(end, std::string("Unknown symbol " + name));
return 0.f;
}

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