Removed some spurious newlines that I introduced into CMakeLists.txt.
commit
8a952e42e9
|
|
@ -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
58
.hgtags
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
4
build.sh
4
build.sh
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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() ;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -266,6 +266,7 @@ public:
|
|||
void setSkeletonSerialNum( U32 num ) { mSkeletonSerialNum = num; }
|
||||
|
||||
static std::vector< LLCharacter* > sInstances;
|
||||
static BOOL sAllowInstancesChange ; //debug use
|
||||
|
||||
protected:
|
||||
LLMotionController mMotionController;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
//-------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)) ;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,8 +35,6 @@ class LL_COMMON_API LLCommon
|
|||
public:
|
||||
static void initClass();
|
||||
static void cleanupClass();
|
||||
private:
|
||||
static BOOL sAprInitialized;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -30,8 +30,7 @@
|
|||
|
||||
LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
|
||||
: LLLineBuffer(),
|
||||
mMaxLines(max_lines),
|
||||
mMutex(NULL)
|
||||
mMaxLines(max_lines)
|
||||
{
|
||||
mTimer.reset();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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?";
|
||||
|
|
|
|||
|
|
@ -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:]))
|
||||
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ private:
|
|||
};
|
||||
typedef std::list<creation_info> creation_list_t;
|
||||
creation_list_t mCreationList;
|
||||
LLMutex* mCreationMutex;
|
||||
LLMutex mCreationMutex;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ set(llkdu_SOURCE_FILES
|
|||
|
||||
set(llkdu_HEADER_FILES
|
||||
CMakeLists.txt
|
||||
|
||||
|
||||
llimagej2ckdu.h
|
||||
llkdumem.h
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
Loading…
Reference in New Issue