Compare commits
482 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0aa0dad478 | |||
| 3aa99b9a7f | |||
| 14a31c3e9b | |||
| 94d0ae0d91 | |||
| 0eaca7aafb | |||
| 2ff9ea3f80 | |||
| a2ea844494 | |||
| 0300ec45eb | |||
| 22dade6463 | |||
| db5a42ffac | |||
| eaf595c008 | |||
| d6f9f690e5 | |||
| 02a53665c9 | |||
| bf5320eb26 | |||
| 3c992b028c | |||
| a755c57b44 | |||
| 9ced61fbc2 | |||
| 0eede1467f | |||
| 35c7fb2038 | |||
| 8656b5e948 | |||
| 1efaf0c85c | |||
| 27597463da | |||
| c32ccfb520 | |||
| 9ca86664bb | |||
| 464d31b70b | |||
| 5622cf68aa | |||
| 394ec508f6 | |||
| bcaacb4e41 | |||
| d131c57978 | |||
| 987c56984d | |||
| e19c830a6c | |||
| fab0389cb1 | |||
| d2877b9cd4 | |||
| b778bd9423 | |||
| 449548d7a4 | |||
| 33cc847c4a | |||
| 5aeaa7fcdd | |||
| e68867c9b6 | |||
| 1fa3a6f1bd | |||
| ff9da24465 | |||
| 227685bea4 | |||
| 20f20895cf | |||
| 9bae636ff0 | |||
| cf95b65c10 | |||
| 250ea09328 | |||
| b3a496d6f2 | |||
| f55e153636 | |||
| fbcb76383d | |||
| 72c67c5091 | |||
| 5015b0b485 | |||
| c78a8271c4 | |||
| fbed245596 | |||
| 174df94172 | |||
| 3fbaef9275 | |||
| 16bf38e1ab | |||
| f8b8241239 | |||
| bffc9ad184 | |||
| 15b50ae737 | |||
| 65a135f4d3 | |||
| 1b156b7fe8 | |||
| b7c7293c7a | |||
| f7b2aa0f49 | |||
| 04aa13a086 | |||
| 251b93d97e | |||
| a1b291c889 | |||
| 5b433e101d | |||
| d93275745b | |||
| 32070fa5f4 | |||
| 9479f64778 | |||
| 5ec3429843 | |||
| 77a331fce3 | |||
| b46be88db6 | |||
| 3a6f312484 | |||
| 47b84875fd | |||
| 78733b979f | |||
| dd30a29ba0 | |||
| 882af7195c | |||
| 96e5836b50 | |||
| ab1472e5b7 | |||
| 922f76a3a7 | |||
| 0be9e3b079 | |||
| 4a74c4533c | |||
| d2c738fc09 | |||
| 6dc1b113d0 | |||
| d32d25634d | |||
| 7c12dfe185 | |||
| 2f7539a25b | |||
| 0c0ee95bd8 | |||
| c23d37a509 | |||
| 4569c595bf | |||
| 484aa72ff8 | |||
| 8ad29fc5c8 | |||
| 87e2668529 | |||
| 515d373a8e | |||
| bbc1dc6bce | |||
| 8457044b2f | |||
| 19d8f05584 | |||
| 7db4336f1c | |||
| faf9ba53fc | |||
| bf8f64e40e | |||
| 73891c7fd3 | |||
| 667a272cce | |||
| f41809e07d | |||
| afb938e579 | |||
| a31393ba0b | |||
| a845c1a893 | |||
| 093705efd1 | |||
| f4cba27105 | |||
| 3db9b847bf | |||
| 2b33677402 | |||
| 812f5e124d | |||
| 2fbafc7465 | |||
| e44450cce1 | |||
| 78015bbbdc | |||
| 9e83b43009 | |||
| 8b3c2f7d0c | |||
| cecb446e0e | |||
| 0faba7dc33 | |||
| e245638f24 | |||
| c9742c826d | |||
| 539165e6bd | |||
| 95eeb4dde8 | |||
| ef262799ca | |||
| 614b9e14c4 | |||
| eb79c882ea | |||
| 1e5cff32fc | |||
| df49196e17 | |||
| 0fe08c8799 | |||
| 7862d1e20d | |||
| 13b2ac1425 | |||
| 7f570636f8 | |||
| 5a10da3ee8 | |||
| 53b72ab4b8 | |||
| 3a2c099169 | |||
| c31d93cb6f | |||
| f0411dc128 | |||
| 7c121a2acc | |||
| f0eeb47262 | |||
| 44f533d95a | |||
| 7bb673a854 | |||
| 5d01a1ff4d | |||
| 253110293a | |||
| 5fc61942e0 | |||
| d4eee213a9 | |||
| 2dbc18054e | |||
| 88f7a833dc | |||
| 06e4fcd260 | |||
| df89e15290 | |||
| 63aea3a5f2 | |||
| cb8c3ba023 | |||
| 2e216aa056 | |||
| 9664273df6 | |||
| 2227f51b29 | |||
| 38acda9f29 | |||
| 904baa6da6 | |||
| a108fcac95 | |||
| 2572ed9ed9 | |||
| cf54df3ecf | |||
| 1d9a9e6004 | |||
| 0d898d8d8a | |||
| 463d0b2f8f | |||
| bc06db3df4 | |||
| e8a2eff2e8 | |||
| d62f0bc35d | |||
| d15a3b10a3 | |||
| 6efc203ce8 | |||
| d1865c526d | |||
| 98c1940820 | |||
| 5dc0298f83 | |||
| 7180690a14 | |||
| 0b743045ef | |||
| 5092cbd77e | |||
| cb1f2886cd | |||
| 7a5699224e | |||
| 328bc3b76e | |||
| b01e73cf27 | |||
| 7eb12f96ec | |||
| 2506b3d89e | |||
| 018832522c | |||
| ca78c8326e | |||
| 998d7009a6 | |||
| 617bc4710a | |||
| 2c9859314f | |||
| eb5bfd14fa | |||
| 85f4357ce6 | |||
| a893fd90cd | |||
| 93a9ed2a6d | |||
| 4cac87d9f4 | |||
| 538ff31b28 | |||
| 06db136fbc | |||
| acc2c42a79 | |||
| b065c02661 | |||
| bc969a6b46 | |||
| 3f76f72137 | |||
| 52f8669169 | |||
| 853c0fccc8 | |||
| 090f9bcece | |||
| 3185db7f94 | |||
| a780e01a54 | |||
| 63fd027494 | |||
| b3ebec184f | |||
| e1dd228f18 | |||
| c8914d22eb | |||
| 574a11558d | |||
| 5d964a6424 | |||
| 18b91fdbe9 | |||
| f0998a9222 | |||
| 7c148d9b2f | |||
| de0ab04d00 | |||
| 530c86335d | |||
| 562a3cb338 | |||
| 32ad66c274 | |||
| c725ad1577 | |||
| 06e0528d0b | |||
| cf1686335f | |||
| af406748a2 | |||
| e00f1a0410 | |||
| 86105a1533 | |||
| c0fd09b445 | |||
| 85d51e57a9 | |||
| 55cc8044cb | |||
| f3508649f5 | |||
| abe0f4a088 | |||
| d4acaf25af | |||
| cacbb5c165 | |||
| 86a2cd915c | |||
| 2c00b73cd2 | |||
| 8b8e1b88ec | |||
| aec723b955 | |||
| 6b1d09813e | |||
| 50eec6df52 | |||
| 3c5b7d7b79 | |||
| 4aa483777b | |||
| 672bd9fc98 | |||
| 01daa74adf | |||
| 6d2893be67 | |||
| 65c4cb48ac | |||
| 9406db3047 | |||
| e756457703 | |||
| 6ac9c9c972 | |||
| 91b7679db9 | |||
| 17929abd28 | |||
| 5cb4044539 | |||
| e6d0dcd4e8 | |||
| 2051535ce1 | |||
| 0301c81b01 | |||
| 9211361b19 | |||
| 6b65895736 | |||
| 559c66afe6 | |||
| aa217cf90f | |||
| bbfda8e19e | |||
| fad0fd7f75 | |||
| d1c3f8eef5 | |||
| ac16a667e1 | |||
| 7bafee28fa | |||
| 46095c058e | |||
| e5a5b69b08 | |||
| 43eab5e163 | |||
| 444737c830 | |||
| 7cb1690589 | |||
| 0af8886400 | |||
| 4cbd45f3d5 | |||
| 59d0e3c3c8 | |||
| 635f3f77ab | |||
| 6557eba235 | |||
| 1fe504fee5 | |||
| f360b687d6 | |||
| ba5a236922 | |||
| 20640357ab | |||
| 45ada5ca2d | |||
| 9c7b28341c | |||
| a15282f023 | |||
| 161c827a44 | |||
| 76add0fdb0 | |||
| af54e6f370 | |||
| e7fa8a4699 | |||
| 262892336b | |||
| 1247174db4 | |||
| de941d2ec7 | |||
| b0bae62c30 | |||
| 7a4c5b067d | |||
| 6c447f892e | |||
| 5e8dfb4f7e | |||
| 7a47c15edb | |||
| 14a7ddb885 | |||
| 2fbb906ff6 | |||
| 62a03a5cac | |||
| d3387d591a | |||
| cffea984f1 | |||
| 99308d64c6 | |||
| 6d1d58b654 | |||
| 14836e60ff | |||
| 9aec36156e | |||
| fce3fca7f9 | |||
| 542bef20e8 | |||
| dba33fee39 | |||
| b1d8aa0b64 | |||
| 8ecab21b37 | |||
| 368b29a680 | |||
| f90aee696a | |||
| f901a38204 | |||
| 4289b71141 | |||
| e131e73652 | |||
| 84d7227dfd | |||
| b13214af27 | |||
| e735f76553 | |||
| 4031933475 | |||
| 8555e54e22 | |||
| 7c0ebcb984 | |||
| 091f3a8000 | |||
| e12c044eab | |||
| 8276a9e5f7 | |||
| 6a477e044d | |||
| 1769e93c42 | |||
| 1a32b35279 | |||
| 305f5110c6 | |||
| 35078e03e5 | |||
| 5fd9411143 | |||
| 0ff61341e4 | |||
| 8cec0b3fa1 | |||
| 1b30ae81b5 | |||
| b9e0d0fdb2 | |||
| 1d4551e52f | |||
| c8583e566d | |||
| a2dd8f31de | |||
| 6edc446780 | |||
| bf68dbabd7 | |||
| 89945f8829 | |||
| edc04d4184 | |||
| 5b2af7f99e | |||
| df9845a283 | |||
| 7496d0b0f7 | |||
| 4bccfed80c | |||
| eaf99bf928 | |||
| f5ae36d7e2 | |||
| 425d76bb98 | |||
| 921f0052f4 | |||
| 6734b94761 | |||
| 773ffcafc3 | |||
| 62b3bdf0fc | |||
| b0cb0ec02f | |||
| 81c9952e99 | |||
| db83208794 | |||
| ff5c38534d | |||
| 58d7e3b8ed | |||
| 949139eb0b | |||
| fe16a72a9a | |||
| 58def34dbe | |||
| d4dad75a3c | |||
| ebe7726cd7 | |||
| a4d322dcd1 | |||
| ccf18fd2ef | |||
| 3d0778bcd6 | |||
| a5800f479e | |||
| 178a5a5585 | |||
| 6664079f84 | |||
| fb312279c9 | |||
| f8caf41bd8 | |||
| 47e7febebc | |||
| 33ae733006 | |||
| da25903300 | |||
| 7f027552ec | |||
| d04bb3ca9b | |||
| bd6f734d3a | |||
| b5f94c72b9 | |||
| 220ea9f687 | |||
| 61353dde80 | |||
| cf97535d9e | |||
| 52b7b40034 | |||
| 1497b75361 | |||
| 9858766516 | |||
| e6080a38c5 | |||
| 1d0a9e521c | |||
| fad1d70180 | |||
| 9e0d419239 | |||
| eed343ed8a | |||
| 7df325c275 | |||
| fdcd392582 | |||
| f27766d47b | |||
| a660c0a750 | |||
| 8ce3fa646b | |||
| e82d394ddf | |||
| d5f5649750 | |||
| c605c7a7b7 | |||
| a53272c5fb | |||
| ae56b946cf | |||
| 01520bbb3e | |||
| f3e177814a | |||
| 873eee5431 | |||
| 6a279feb2f | |||
| 296d63e20b | |||
| beba20846f | |||
| 7112ee0015 | |||
| 86630a1b70 | |||
| d975b42f6a | |||
| 8edf4225f3 | |||
| 6b17c9bd98 | |||
| 71c808cd32 | |||
| 3e8f593bf2 | |||
| 742f505440 | |||
| 0237d9113d | |||
| 120f872d2b | |||
| 932c9e757b | |||
| 77e7bbcbf7 | |||
| 4f67286044 | |||
| cfd3e8f0ea | |||
| abcb2cdb36 | |||
| a96601478c | |||
| e3c4936dea | |||
| da990d01f2 | |||
| 12f2648a57 | |||
| 9de3fe9410 | |||
| 8225e3f40c | |||
| 3c05d67094 | |||
| 6b7625a56b | |||
| 71918eeab4 | |||
| ddd38a3dea | |||
| 58c0ed78d4 | |||
| 470d053443 | |||
| ed14e97bb4 | |||
| aa2fb1ec25 | |||
| 14569992e1 | |||
| 4e6f7435d0 | |||
| 39ed382ddf | |||
| c9415fd763 | |||
| 31de7b845f | |||
| 5038a59ef3 | |||
| 88b1fc1382 | |||
| 94ad69faf2 | |||
| 5fafea6631 | |||
| 1f4f09ad69 | |||
| 91333b9267 | |||
| ed760f2586 | |||
| d7c9725ec0 | |||
| 6955190c7d | |||
| ce5d308d23 | |||
| 0e23374aa2 | |||
| 26fe59c35e | |||
| bc9952f901 | |||
| fd1b2a1c57 | |||
| 0f03c64a0c | |||
| d6837f5dc7 | |||
| 0b213af675 | |||
| cddf1ec0dc | |||
| 97c74afca8 | |||
| d27e188fe2 | |||
| 11b4f534c2 | |||
| d50d169441 | |||
| 28419251bf | |||
| d1bb73d068 | |||
| 4d1426e77d | |||
| a2866b85f3 | |||
| 269a6410a0 | |||
| c26f01ff8c | |||
| fc9930e420 | |||
| 79200ed270 | |||
| 7fc289c039 | |||
| 877bdcdce1 | |||
| bdbbeaa494 | |||
| f6913e911e | |||
| f74aafaf63 | |||
| 4fed301e65 | |||
| 733e067958 | |||
| ffd0da23fb | |||
| f49d513089 | |||
| fc35b45e21 | |||
| bc7fda39b4 | |||
| e10012a7a6 | |||
| 3a7c8d1f32 | |||
| c0cc5e0fa4 | |||
| b83a224147 | |||
| 4a1c1fc009 | |||
| cf61cdf58c | |||
| 1913ab5ad5 | |||
| 29c8461631 | |||
| 8f372b8ac8 | |||
| 342be228c6 | |||
| 87abf06956 | |||
| f81841a2c5 | |||
| 1b41ec0a85 | |||
| 31cba5aa66 | |||
| 1aed6567a8 |
+5
-1
@@ -19,10 +19,14 @@ Prereqs:
|
||||
|
||||
From the distribution type:
|
||||
* ./runprebuild.sh
|
||||
* nant (or xbuild)
|
||||
* nant (or !* xbuild)
|
||||
* cd bin
|
||||
* copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include
|
||||
* run mono OpenSim.exe
|
||||
!* xbuild option switches
|
||||
!* clean: xbuild /target:clean
|
||||
!* debug: (default) xbuild /property:Configuration=Debug
|
||||
!* release: xbuild /property:Configuration=Release
|
||||
|
||||
# Using Monodevelop
|
||||
|
||||
|
||||
+16
-7
@@ -9,13 +9,15 @@ people that make the day to day of OpenSim happen.
|
||||
* dahlia
|
||||
* Melanie Thielker
|
||||
* Diva (Crista Lopes, University of California, Irvine)
|
||||
* Dan Lake (Intel)
|
||||
* Dan Lake
|
||||
* Marck
|
||||
* Mic Bowman (Intel)
|
||||
* Mic Bowman
|
||||
* BlueWall (James Hughes)
|
||||
* Nebadon Izumi (Michael Cerquoni, OSgrid)
|
||||
* Snoopy Pfeffer
|
||||
* Robert Adams (Intel)
|
||||
* Robert Adams
|
||||
* Oren Hurvitz (Kitely)
|
||||
* Kevin Cozens
|
||||
|
||||
= Core Developers Following the White Rabbit =
|
||||
Core developers who have temporarily (we hope) gone chasing the white rabbit.
|
||||
@@ -78,12 +80,13 @@ what it is today.
|
||||
* ctrlaltdavid (David Rowe)
|
||||
* Daedius
|
||||
* daTwitch
|
||||
* Dev Random
|
||||
* devalnor-#708
|
||||
* dmiles (Daxtron Labs)
|
||||
* Dong Jun Lan (IBM)
|
||||
* DoranZemlja
|
||||
* dr0b3rts
|
||||
* dslake (Intel)
|
||||
* dslake
|
||||
* FredoChaplin
|
||||
* Garmin Kawaguichi
|
||||
* Gerhard
|
||||
@@ -97,10 +100,12 @@ what it is today.
|
||||
* Flyte Xevious
|
||||
* Garmin Kawaguichi
|
||||
* Gryc Ueusp
|
||||
* H-H-H (ginge264)
|
||||
* Hiro Lecker
|
||||
* Iain Oliver
|
||||
* Imaze Rhiano
|
||||
* Intimidated
|
||||
* Jak Daniels
|
||||
* Jeremy Bongio (IBM)
|
||||
* jhurliman
|
||||
* John R Sohn (XenReborn)
|
||||
@@ -108,26 +113,30 @@ what it is today.
|
||||
* Jon Cundill
|
||||
* Junta Kohime
|
||||
* Kayne
|
||||
* Kevin Cozens
|
||||
* kinoc (Daxtron Labs)
|
||||
* Kira
|
||||
* Kitto Flora
|
||||
* KittyLiu
|
||||
* Kurt Taylor (IBM)
|
||||
* Lani Global
|
||||
* lillith_xue
|
||||
* lkalif
|
||||
* LuciusSirnah
|
||||
* lulurun
|
||||
* M.Igarashi
|
||||
* maimedleech
|
||||
* Mana Janus
|
||||
* MarcelEdward
|
||||
* Matt Lehmann
|
||||
* Mic Bowman
|
||||
* Michelle Argus
|
||||
* Michael Cortez (The Flotsam Project, http://osflotsam.org/)
|
||||
* Micheil Merlin
|
||||
* Mike Osias (IBM)
|
||||
* Mike Pitman (IBM)
|
||||
* mikemig
|
||||
* mikkopa/_someone - RealXtend
|
||||
* Misterblue (Intel)
|
||||
* Misterblue
|
||||
* Mircea Kitsune
|
||||
* mpallari
|
||||
* MrMonkE
|
||||
@@ -136,7 +145,6 @@ what it is today.
|
||||
* nornalbion
|
||||
* Omar Vera Ustariz (IBM)
|
||||
* openlifegrid.com
|
||||
* Oren Hurvitz (Kitely)
|
||||
* otakup0pe
|
||||
* Pixel Tomsen
|
||||
* ralphos
|
||||
@@ -145,6 +153,7 @@ what it is today.
|
||||
* Richard Alimi (IBM)
|
||||
* Rick Alther (IBM)
|
||||
* Rob Smart (IBM)
|
||||
* Roger Kirkman (zadark)
|
||||
* rtomita
|
||||
* Ruud Lathorp
|
||||
* SachaMagne
|
||||
|
||||
@@ -56,8 +56,8 @@ namespace OpenSim.Groups
|
||||
private IGroupsServicesConnector m_groupData = null;
|
||||
|
||||
// Config Options
|
||||
private bool m_groupMessagingEnabled = false;
|
||||
private bool m_debugEnabled = true;
|
||||
private bool m_groupMessagingEnabled;
|
||||
private bool m_debugEnabled;
|
||||
|
||||
/// <summary>
|
||||
/// If enabled, module only tries to send group IMs to online users by querying cached presence information.
|
||||
@@ -83,7 +83,6 @@ namespace OpenSim.Groups
|
||||
private Dictionary<UUID, List<string>> m_groupsAgentsDroppedFromChatSession = new Dictionary<UUID, List<string>>();
|
||||
private Dictionary<UUID, List<string>> m_groupsAgentsInvitedToChatSession = new Dictionary<UUID, List<string>>();
|
||||
|
||||
|
||||
#region Region Module interfaceBase Members
|
||||
|
||||
public void Initialise(IConfigSource config)
|
||||
@@ -111,9 +110,17 @@ namespace OpenSim.Groups
|
||||
m_messageOnlineAgentsOnly = groupsConfig.GetBoolean("MessageOnlineUsersOnly", false);
|
||||
|
||||
if (m_messageOnlineAgentsOnly)
|
||||
{
|
||||
m_usersOnlineCache = new ExpiringCache<UUID, PresenceInfo[]>();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Error("[Groups.Messaging]: GroupsMessagingModule V2 requires MessageOnlineUsersOnly = true");
|
||||
m_groupMessagingEnabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true);
|
||||
m_debugEnabled = groupsConfig.GetBoolean("MessagingDebugEnabled", m_debugEnabled);
|
||||
|
||||
m_log.InfoFormat(
|
||||
"[Groups.Messaging]: GroupsMessagingModule enabled with MessageOnlineOnly = {0}, DebugEnabled = {1}",
|
||||
@@ -133,6 +140,14 @@ namespace OpenSim.Groups
|
||||
scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
|
||||
scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
|
||||
scene.EventManager.OnClientLogin += OnClientLogin;
|
||||
|
||||
scene.AddCommand(
|
||||
"Debug",
|
||||
this,
|
||||
"debug groups messaging verbose",
|
||||
"debug groups messaging verbose <true|false>",
|
||||
"This setting turns on very verbose groups messaging debugging",
|
||||
HandleDebugGroupsMessagingVerbose);
|
||||
}
|
||||
|
||||
public void RegionLoaded(Scene scene)
|
||||
@@ -172,10 +187,8 @@ namespace OpenSim.Groups
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (m_presenceService == null)
|
||||
m_presenceService = scene.PresenceService;
|
||||
|
||||
}
|
||||
|
||||
public void RemoveRegion(Scene scene)
|
||||
@@ -222,6 +235,25 @@ namespace OpenSim.Groups
|
||||
|
||||
#endregion
|
||||
|
||||
private void HandleDebugGroupsMessagingVerbose(object modules, string[] args)
|
||||
{
|
||||
if (args.Length < 5)
|
||||
{
|
||||
MainConsole.Instance.Output("Usage: debug groups messaging verbose <true|false>");
|
||||
return;
|
||||
}
|
||||
|
||||
bool verbose = false;
|
||||
if (!bool.TryParse(args[4], out verbose))
|
||||
{
|
||||
MainConsole.Instance.Output("Usage: debug groups messaging verbose <true|false>");
|
||||
return;
|
||||
}
|
||||
|
||||
m_debugEnabled = verbose;
|
||||
|
||||
MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not really needed, but does confirm that the group exists.
|
||||
@@ -242,11 +274,23 @@ namespace OpenSim.Groups
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SendMessageToGroup(GridInstantMessage im, UUID groupID)
|
||||
{
|
||||
SendMessageToGroup(im, groupID, UUID.Zero, null);
|
||||
}
|
||||
|
||||
public void SendMessageToGroup(
|
||||
GridInstantMessage im, UUID groupID, UUID sendingAgentForGroupCalls, Func<GroupMembersData, bool> sendCondition)
|
||||
{
|
||||
int requestStartTick = Environment.TickCount;
|
||||
|
||||
UUID fromAgentID = new UUID(im.fromAgentID);
|
||||
|
||||
// Unlike current XmlRpcGroups, Groups V2 can accept UUID.Zero when a perms check for the requesting agent
|
||||
// is not necessary.
|
||||
List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(UUID.Zero.ToString(), groupID);
|
||||
|
||||
int groupMembersCount = groupMembers.Count;
|
||||
PresenceInfo[] onlineAgents = null;
|
||||
|
||||
@@ -254,7 +298,7 @@ namespace OpenSim.Groups
|
||||
// Sending to offline members is not an option.
|
||||
string[] t1 = groupMembers.ConvertAll<string>(gmd => gmd.AgentID.ToString()).ToArray();
|
||||
|
||||
// We cache in order not to overwhlem the presence service on large grids with many groups. This does
|
||||
// We cache in order not to overwhelm the presence service on large grids with many groups. This does
|
||||
// mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed.
|
||||
// (assuming this is the same across all grid simulators).
|
||||
if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents))
|
||||
@@ -273,8 +317,6 @@ namespace OpenSim.Groups
|
||||
// "[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members, {2} online",
|
||||
// groupID, groupMembersCount, groupMembers.Count());
|
||||
|
||||
int requestStartTick = Environment.TickCount;
|
||||
|
||||
im.imSessionID = groupID.Guid;
|
||||
im.fromGroup = true;
|
||||
IClientAPI thisClient = GetActiveClient(fromAgentID);
|
||||
@@ -299,12 +341,27 @@ namespace OpenSim.Groups
|
||||
|
||||
if (clientsAlreadySent.Contains(member.AgentID))
|
||||
continue;
|
||||
|
||||
clientsAlreadySent.Add(member.AgentID);
|
||||
|
||||
if (hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID))
|
||||
if (sendCondition != null)
|
||||
{
|
||||
if (!sendCondition(member))
|
||||
{
|
||||
if (m_debugEnabled)
|
||||
m_log.DebugFormat(
|
||||
"[Groups.Messaging]: Not sending to {0} as they do not fulfill send condition",
|
||||
member.AgentID);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID))
|
||||
{
|
||||
// Don't deliver messages to people who have dropped this session
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} has dropped session, not delivering to them", member.AgentID);
|
||||
if (m_debugEnabled)
|
||||
m_log.DebugFormat("[Groups.Messaging]: {0} has dropped session, not delivering to them", member.AgentID);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,9 +45,6 @@ namespace OpenSim.Groups
|
||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsModule")]
|
||||
public class GroupsModule : ISharedRegionModule, IGroupsModule
|
||||
{
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
@@ -104,7 +101,7 @@ namespace OpenSim.Groups
|
||||
{
|
||||
scene.RegisterModuleInterface<IGroupsModule>(this);
|
||||
scene.AddCommand(
|
||||
"debug",
|
||||
"Debug",
|
||||
this,
|
||||
"debug groups verbose",
|
||||
"debug groups verbose <true|false>",
|
||||
@@ -466,6 +463,7 @@ namespace OpenSim.Groups
|
||||
OnNewGroupNotice(GroupID, NoticeID);
|
||||
}
|
||||
|
||||
|
||||
// Send notice out to everyone that wants notices
|
||||
foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentIDStr(remoteClient), GroupID))
|
||||
{
|
||||
@@ -498,12 +496,13 @@ namespace OpenSim.Groups
|
||||
Util.ParseUniversalUserIdentifier(notice.noticeData.AttachmentOwnerID, out giver, out tmp, out tmp, out tmp, out tmp);
|
||||
|
||||
m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId);
|
||||
string message;
|
||||
InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId,
|
||||
giver, notice.noticeData.AttachmentItemID);
|
||||
giver, notice.noticeData.AttachmentItemID, out message);
|
||||
|
||||
if (itemCopy == null)
|
||||
{
|
||||
remoteClient.SendAgentAlertMessage("Can't find item to give. Nothing given.", false);
|
||||
remoteClient.SendAgentAlertMessage(message, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
@@ -560,7 +560,7 @@ namespace OpenSim.Groups
|
||||
|
||||
// so we have the list of urls to send the notice to
|
||||
// this may take a long time...
|
||||
Util.FireAndForget(delegate
|
||||
Util.RunThreadNoTimeout(delegate
|
||||
{
|
||||
foreach (string u in urls)
|
||||
{
|
||||
@@ -571,7 +571,7 @@ namespace OpenSim.Groups
|
||||
hasAttachment, attType, attName, attItemID, AgentUUIForOutside(attOwnerID));
|
||||
}
|
||||
}
|
||||
});
|
||||
}, "AddGroupNotice", null);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
@@ -158,7 +158,7 @@ namespace OpenSim.Groups
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[Groups.RobustHGConnector]: Exception {0}", e.StackTrace);
|
||||
m_log.Error(string.Format("[Groups.RobustHGConnector]: Exception {0} ", e.Message), e);
|
||||
}
|
||||
|
||||
return FailureResult();
|
||||
|
||||
@@ -32,27 +32,47 @@ using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.ServiceAuth;
|
||||
using OpenSim.Server.Base;
|
||||
|
||||
using OpenMetaverse;
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
|
||||
namespace OpenSim.Groups
|
||||
{
|
||||
public class GroupsServiceRemoteConnector
|
||||
public class GroupsServiceRemoteConnector
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private string m_ServerURI;
|
||||
private IServiceAuth m_Auth;
|
||||
private object m_Lock = new object();
|
||||
|
||||
public GroupsServiceRemoteConnector(string url)
|
||||
public GroupsServiceRemoteConnector(IConfigSource config)
|
||||
{
|
||||
IConfig groupsConfig = config.Configs["Groups"];
|
||||
string url = groupsConfig.GetString("GroupsServerURI", string.Empty);
|
||||
if (!Uri.IsWellFormedUriString(url, UriKind.Absolute))
|
||||
throw new Exception(string.Format("[Groups.RemoteConnector]: Malformed groups server URL {0}. Fix it or disable the Groups feature.", url));
|
||||
|
||||
m_ServerURI = url;
|
||||
if (!m_ServerURI.EndsWith("/"))
|
||||
m_ServerURI += "/";
|
||||
|
||||
m_log.DebugFormat("[Groups.RemoteConnector]: Groups server at {0}", m_ServerURI);
|
||||
/// This is from BaseServiceConnector
|
||||
string authType = Util.GetConfigVarFromSections<string>(config, "AuthType", new string[] { "Network", "Groups" }, "None");
|
||||
|
||||
switch (authType)
|
||||
{
|
||||
case "BasicHttpAuthentication":
|
||||
m_Auth = new BasicHttpAuthentication(config, "Groups");
|
||||
break;
|
||||
}
|
||||
///
|
||||
|
||||
m_log.DebugFormat("[Groups.RemoteConnector]: Groups server at {0}, authentication {1}",
|
||||
m_ServerURI, (m_Auth == null ? "None" : m_Auth.GetType().ToString()));
|
||||
}
|
||||
|
||||
public ExtendedGroupRecord CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
|
||||
@@ -106,7 +126,7 @@ namespace OpenSim.Groups
|
||||
sendData["OP"] = "UPDATE";
|
||||
Dictionary<string, object> ret = MakeRequest("PUTGROUP", sendData);
|
||||
|
||||
if (ret == null || (ret != null && ret["RESULT"].ToString() == "NULL"))
|
||||
if (ret == null || (ret != null && (!ret.ContainsKey("RESULT") || ret["RESULT"].ToString() == "NULL")))
|
||||
return null;
|
||||
|
||||
return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
|
||||
@@ -127,7 +147,7 @@ namespace OpenSim.Groups
|
||||
|
||||
Dictionary<string, object> ret = MakeRequest("GETGROUP", sendData);
|
||||
|
||||
if (ret == null || (ret != null && ret["RESULT"].ToString() == "NULL"))
|
||||
if (ret == null || (ret != null && (!ret.ContainsKey("RESULT") || ret["RESULT"].ToString() == "NULL")))
|
||||
return null;
|
||||
|
||||
return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
|
||||
@@ -267,6 +287,7 @@ namespace OpenSim.Groups
|
||||
|
||||
if (ret["RESULT"].ToString() == "NULL")
|
||||
return members;
|
||||
|
||||
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||
{
|
||||
ExtendedGroupMembersData m = GroupsDataUtils.GroupMembersData((Dictionary<string, object>)v);
|
||||
@@ -357,6 +378,7 @@ namespace OpenSim.Groups
|
||||
|
||||
if (ret["RESULT"].ToString() == "NULL")
|
||||
return roles;
|
||||
|
||||
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||
{
|
||||
GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary<string, object>)v);
|
||||
@@ -657,7 +679,8 @@ namespace OpenSim.Groups
|
||||
lock (m_Lock)
|
||||
reply = SynchronousRestFormsRequester.MakeRequest("POST",
|
||||
m_ServerURI + "groups",
|
||||
ServerUtils.BuildQueryString(sendData));
|
||||
ServerUtils.BuildQueryString(sendData),
|
||||
m_Auth);
|
||||
|
||||
if (reply == string.Empty)
|
||||
return null;
|
||||
@@ -667,7 +690,7 @@ namespace OpenSim.Groups
|
||||
|
||||
return replyData;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,12 +72,7 @@ namespace OpenSim.Groups
|
||||
|
||||
private void Init(IConfigSource config)
|
||||
{
|
||||
IConfig groupsConfig = config.Configs["Groups"];
|
||||
string url = groupsConfig.GetString("GroupsServerURI", string.Empty);
|
||||
if (!Uri.IsWellFormedUriString(url, UriKind.Absolute))
|
||||
throw new Exception(string.Format("[Groups.RemoteConnector]: Malformed groups server URL {0}. Fix it or disable the Groups feature.", url));
|
||||
|
||||
m_GroupsService = new GroupsServiceRemoteConnector(url);
|
||||
m_GroupsService = new GroupsServiceRemoteConnector(config);
|
||||
m_Scenes = new List<Scene>();
|
||||
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ using OpenSim.Framework;
|
||||
using OpenSim.Server.Base;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
using OpenSim.Framework.ServiceAuth;
|
||||
using OpenSim.Server.Handlers.Base;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
@@ -52,14 +53,26 @@ namespace OpenSim.Groups
|
||||
public GroupsServiceRobustConnector(IConfigSource config, IHttpServer server, string configName) :
|
||||
base(config, server, configName)
|
||||
{
|
||||
string key = string.Empty;
|
||||
if (configName != String.Empty)
|
||||
m_ConfigName = configName;
|
||||
|
||||
m_log.DebugFormat("[Groups.RobustConnector]: Starting with config name {0}", m_ConfigName);
|
||||
|
||||
IConfig groupsConfig = config.Configs[m_ConfigName];
|
||||
if (groupsConfig != null)
|
||||
{
|
||||
key = groupsConfig.GetString("SecretKey", string.Empty);
|
||||
m_log.DebugFormat("[Groups.RobustConnector]: Starting with secret key {0}", key);
|
||||
}
|
||||
// else
|
||||
// m_log.DebugFormat("[Groups.RobustConnector]: Unable to find {0} section in configuration", m_ConfigName);
|
||||
|
||||
m_GroupsService = new GroupsService(config);
|
||||
|
||||
server.AddStreamHandler(new GroupsServicePostHandler(m_GroupsService));
|
||||
IServiceAuth auth = ServiceAuth.Create(config, m_ConfigName);
|
||||
|
||||
server.AddStreamHandler(new GroupsServicePostHandler(m_GroupsService, auth));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,8 +82,8 @@ namespace OpenSim.Groups
|
||||
|
||||
private GroupsService m_GroupsService;
|
||||
|
||||
public GroupsServicePostHandler(GroupsService service) :
|
||||
base("POST", "/groups")
|
||||
public GroupsServicePostHandler(GroupsService service, IServiceAuth auth) :
|
||||
base("POST", "/groups", auth)
|
||||
{
|
||||
m_GroupsService = service;
|
||||
}
|
||||
@@ -96,7 +109,7 @@ namespace OpenSim.Groups
|
||||
string method = request["METHOD"].ToString();
|
||||
request.Remove("METHOD");
|
||||
|
||||
m_log.DebugFormat("[Groups.Handler]: {0}", method);
|
||||
// m_log.DebugFormat("[Groups.Handler]: {0}", method);
|
||||
switch (method)
|
||||
{
|
||||
case "PUTGROUP":
|
||||
@@ -140,7 +153,7 @@ namespace OpenSim.Groups
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[GROUPS HANDLER]: Exception {0}", e.StackTrace);
|
||||
m_log.Error(string.Format("[GROUPS HANDLER]: Exception {0} ", e.Message), e);
|
||||
}
|
||||
|
||||
return FailureResult();
|
||||
@@ -784,6 +797,14 @@ namespace OpenSim.Groups
|
||||
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||
}
|
||||
|
||||
private byte[] FailureResult(string reason)
|
||||
{
|
||||
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||
NullResult(result, reason);
|
||||
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace OpenSim.OfflineIM
|
||||
if (serviceLocation == string.Empty)
|
||||
m_OfflineIMService = new OfflineIMService(config);
|
||||
else
|
||||
m_OfflineIMService = new OfflineIMServiceRemoteConnector(serviceLocation);
|
||||
m_OfflineIMService = new OfflineIMServiceRemoteConnector(config);
|
||||
|
||||
m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", m_ForwardOfflineGroupMessages);
|
||||
m_log.DebugFormat("[OfflineIM.V2]: Offline messages enabled by {0}", Name);
|
||||
@@ -226,10 +226,6 @@ namespace OpenSim.OfflineIM
|
||||
return;
|
||||
}
|
||||
|
||||
Scene scene = FindScene(new UUID(im.fromAgentID));
|
||||
if (scene == null)
|
||||
scene = m_SceneList[0];
|
||||
|
||||
string reason = string.Empty;
|
||||
bool success = m_OfflineIMService.StoreMessage(im, out reason);
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.ServiceAuth;
|
||||
using OpenSim.Server.Base;
|
||||
using OpenSim.Services.Interfaces;
|
||||
|
||||
@@ -46,6 +47,7 @@ namespace OpenSim.OfflineIM
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private string m_ServerURI = string.Empty;
|
||||
private IServiceAuth m_Auth;
|
||||
private object m_Lock = new object();
|
||||
|
||||
public OfflineIMServiceRemoteConnector(string url)
|
||||
@@ -65,6 +67,18 @@ namespace OpenSim.OfflineIM
|
||||
|
||||
m_ServerURI = cnf.GetString("OfflineMessageURL", string.Empty);
|
||||
|
||||
/// This is from BaseServiceConnector
|
||||
string authType = Util.GetConfigVarFromSections<string>(config, "AuthType", new string[] { "Network", "Messaging" }, "None");
|
||||
|
||||
switch (authType)
|
||||
{
|
||||
case "BasicHttpAuthentication":
|
||||
m_Auth = new BasicHttpAuthentication(config, "Messaging");
|
||||
break;
|
||||
}
|
||||
///
|
||||
m_log.DebugFormat("[OfflineIM.V2.RemoteConnector]: Offline IM server at {0} with auth {1}",
|
||||
m_ServerURI, (m_Auth == null ? "None" : m_Auth.GetType().ToString()));
|
||||
}
|
||||
|
||||
#region IOfflineIMService
|
||||
@@ -82,8 +96,13 @@ namespace OpenSim.OfflineIM
|
||||
if (!ret.ContainsKey("RESULT"))
|
||||
return ims;
|
||||
|
||||
if (ret["RESULT"].ToString() == "NULL")
|
||||
string result = ret["RESULT"].ToString();
|
||||
if (result == "NULL" || result.ToLower() == "false")
|
||||
{
|
||||
string reason = ret.ContainsKey("REASON") ? ret["REASON"].ToString() : "Unknown error";
|
||||
m_log.DebugFormat("[OfflineIM.V2.RemoteConnector]: GetMessages for {0} failed: {1}", principalID, reason);
|
||||
return ims;
|
||||
}
|
||||
|
||||
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||
{
|
||||
@@ -110,7 +129,7 @@ namespace OpenSim.OfflineIM
|
||||
string result = ret["RESULT"].ToString();
|
||||
if (result == "NULL" || result.ToLower() == "false")
|
||||
{
|
||||
reason = ret["REASON"].ToString();
|
||||
reason = ret.ContainsKey("REASON") ? ret["REASON"].ToString() : "Unknown error";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -138,7 +157,8 @@ namespace OpenSim.OfflineIM
|
||||
lock (m_Lock)
|
||||
reply = SynchronousRestFormsRequester.MakeRequest("POST",
|
||||
m_ServerURI + "/offlineim",
|
||||
ServerUtils.BuildQueryString(sendData));
|
||||
ServerUtils.BuildQueryString(sendData),
|
||||
m_Auth);
|
||||
|
||||
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
|
||||
reply);
|
||||
|
||||
@@ -36,6 +36,7 @@ using OpenSim.Framework;
|
||||
using OpenSim.Server.Base;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
using OpenSim.Framework.ServiceAuth;
|
||||
using OpenSim.Server.Handlers.Base;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
@@ -59,7 +60,9 @@ namespace OpenSim.OfflineIM
|
||||
|
||||
m_OfflineIMService = new OfflineIMService(config);
|
||||
|
||||
server.AddStreamHandler(new OfflineIMServicePostHandler(m_OfflineIMService));
|
||||
IServiceAuth auth = ServiceAuth.Create(config, m_ConfigName);
|
||||
|
||||
server.AddStreamHandler(new OfflineIMServicePostHandler(m_OfflineIMService, auth));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,8 +72,8 @@ namespace OpenSim.OfflineIM
|
||||
|
||||
private IOfflineIMService m_OfflineIMService;
|
||||
|
||||
public OfflineIMServicePostHandler(IOfflineIMService service) :
|
||||
base("POST", "/offlineim")
|
||||
public OfflineIMServicePostHandler(IOfflineIMService service, IServiceAuth auth) :
|
||||
base("POST", "/offlineim", auth)
|
||||
{
|
||||
m_OfflineIMService = service;
|
||||
}
|
||||
@@ -109,7 +112,7 @@ namespace OpenSim.OfflineIM
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[OFFLINE IM HANDLER]: Exception {0}", e.StackTrace);
|
||||
m_log.Error(string.Format("[OFFLINE IM HANDLER]: Exception {0} ", e.Message), e);
|
||||
}
|
||||
|
||||
return FailureResult();
|
||||
|
||||
@@ -104,7 +104,7 @@ namespace OpenSim.OfflineIM
|
||||
using (MemoryStream mstream = new MemoryStream())
|
||||
{
|
||||
XmlWriterSettings settings = new XmlWriterSettings();
|
||||
settings.Encoding = Encoding.UTF8;
|
||||
settings.Encoding = Util.UTF8NoBomEncoding;
|
||||
|
||||
using (XmlWriter writer = XmlWriter.Create(mstream, settings))
|
||||
{
|
||||
@@ -112,7 +112,7 @@ namespace OpenSim.OfflineIM
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
imXml = Util.UTF8.GetString(mstream.ToArray());
|
||||
imXml = Util.UTF8NoBomEncoding.GetString(mstream.ToArray());
|
||||
}
|
||||
|
||||
OfflineIMData data = new OfflineIMData();
|
||||
|
||||
@@ -39,6 +39,7 @@ using OpenSim.Region.CoreModules.Avatar.InstantMessage;
|
||||
using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
|
||||
using OpenSim.Region.CoreModules.Scripting.LoadImageURL;
|
||||
using OpenSim.Region.CoreModules.Scripting.XMLRPC;
|
||||
using OpenSim.Services.Interfaces;
|
||||
|
||||
namespace OpenSim.ApplicationPlugins.LoadRegions
|
||||
{
|
||||
@@ -130,7 +131,7 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
|
||||
createdScenes.Add(scene);
|
||||
|
||||
if (changed)
|
||||
regionsToLoad[i].EstateSettings.Save();
|
||||
m_openSim.EstateDataService.StoreEstateSettings(regionsToLoad[i].EstateSettings);
|
||||
}
|
||||
|
||||
foreach (IScene scene in createdScenes)
|
||||
|
||||
@@ -694,7 +694,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
region.EstateSettings.EstateName = (string) requestData["estate_name"];
|
||||
region.EstateSettings.EstateOwner = userID;
|
||||
// Persistence does not seem to effect the need to save a new estate
|
||||
region.EstateSettings.Save();
|
||||
m_application.EstateDataService.StoreEstateSettings(region.EstateSettings);
|
||||
|
||||
if (!m_application.EstateDataService.LinkRegion(region.RegionID, (int) region.EstateSettings.EstateID))
|
||||
throw new Exception("Failed to join estate.");
|
||||
@@ -724,7 +724,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
// If an access specification was provided, use it.
|
||||
// Otherwise accept the default.
|
||||
newScene.RegionInfo.EstateSettings.PublicAccess = GetBoolean(requestData, "public", m_publicAccess);
|
||||
newScene.RegionInfo.EstateSettings.Save();
|
||||
m_application.EstateDataService.StoreEstateSettings(newScene.RegionInfo.EstateSettings);
|
||||
|
||||
// enable voice on newly created region if
|
||||
// requested by either the XmlRpc request or the
|
||||
@@ -910,7 +910,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
scene.RegionInfo.EstateSettings.PublicAccess =
|
||||
GetBoolean(requestData,"public", scene.RegionInfo.EstateSettings.PublicAccess);
|
||||
if (scene.RegionInfo.Persistent)
|
||||
scene.RegionInfo.EstateSettings.Save();
|
||||
m_application.EstateDataService.StoreEstateSettings(scene.RegionInfo.EstateSettings);
|
||||
|
||||
if (requestData.ContainsKey("enable_voice"))
|
||||
{
|
||||
@@ -1792,7 +1792,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
scene.RegionInfo.EstateSettings.EstateAccess = new UUID[]{};
|
||||
|
||||
if (scene.RegionInfo.Persistent)
|
||||
scene.RegionInfo.EstateSettings.Save();
|
||||
m_application.EstateDataService.StoreEstateSettings(scene.RegionInfo.EstateSettings);
|
||||
|
||||
m_log.Info("[RADMIN]: Access List Clear Request complete");
|
||||
}
|
||||
@@ -1838,7 +1838,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
}
|
||||
scene.RegionInfo.EstateSettings.EstateAccess = accessControlList.ToArray();
|
||||
if (scene.RegionInfo.Persistent)
|
||||
scene.RegionInfo.EstateSettings.Save();
|
||||
m_application.EstateDataService.StoreEstateSettings(scene.RegionInfo.EstateSettings);
|
||||
}
|
||||
|
||||
responseData["added"] = addedUsers;
|
||||
@@ -1887,7 +1887,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
}
|
||||
scene.RegionInfo.EstateSettings.EstateAccess = accessControlList.ToArray();
|
||||
if (scene.RegionInfo.Persistent)
|
||||
scene.RegionInfo.EstateSettings.Save();
|
||||
m_application.EstateDataService.StoreEstateSettings(scene.RegionInfo.EstateSettings);
|
||||
}
|
||||
|
||||
responseData["removed"] = removedUsers;
|
||||
@@ -2238,7 +2238,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
{
|
||||
account.ServiceURLs = new Dictionary<string, object>();
|
||||
account.ServiceURLs["HomeURI"] = string.Empty;
|
||||
account.ServiceURLs["GatekeeperURI"] = string.Empty;
|
||||
account.ServiceURLs["InventoryServerURI"] = string.Empty;
|
||||
account.ServiceURLs["AssetServerURI"] = string.Empty;
|
||||
}
|
||||
|
||||
@@ -50,8 +50,7 @@ namespace OpenSim.Framework.Capabilities
|
||||
|
||||
public class Caps
|
||||
{
|
||||
// private static readonly ILog m_log =
|
||||
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private string m_httpListenerHostName;
|
||||
private uint m_httpListenPort;
|
||||
@@ -152,6 +151,10 @@ namespace OpenSim.Framework.Capabilities
|
||||
|
||||
public void RegisterPollHandler(string capName, PollServiceEventArgs pollServiceHandler)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[CAPS]: Registering handler with name {0}, url {1} for {2}",
|
||||
// capName, pollServiceHandler.Url, m_agentID, m_regionName);
|
||||
|
||||
m_pollServiceHandlers.Add(capName, pollServiceHandler);
|
||||
|
||||
m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler.Url, pollServiceHandler);
|
||||
|
||||
@@ -56,12 +56,15 @@ namespace OpenSim.Capabilities.Handlers
|
||||
public const string DefaultFormat = "x-j2c";
|
||||
|
||||
// TODO: Change this to a config option
|
||||
const string REDIRECT_URL = null;
|
||||
private string m_RedirectURL = null;
|
||||
|
||||
public GetTextureHandler(string path, IAssetService assService, string name, string description)
|
||||
public GetTextureHandler(string path, IAssetService assService, string name, string description, string redirectURL)
|
||||
: base("GET", path, name, description)
|
||||
{
|
||||
m_assetService = assService;
|
||||
m_RedirectURL = redirectURL;
|
||||
if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/"))
|
||||
m_RedirectURL += "/";
|
||||
}
|
||||
|
||||
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
@@ -134,7 +137,7 @@ namespace OpenSim.Capabilities.Handlers
|
||||
if (format != DefaultFormat)
|
||||
fullID = fullID + "-" + format;
|
||||
|
||||
if (!String.IsNullOrEmpty(REDIRECT_URL))
|
||||
if (!String.IsNullOrEmpty(m_RedirectURL))
|
||||
{
|
||||
// Only try to fetch locally cached textures. Misses are redirected
|
||||
texture = m_assetService.GetCached(fullID);
|
||||
@@ -150,8 +153,9 @@ namespace OpenSim.Capabilities.Handlers
|
||||
}
|
||||
else
|
||||
{
|
||||
string textureUrl = REDIRECT_URL + textureID.ToString();
|
||||
string textureUrl = m_RedirectURL + "?texture_id="+ textureID.ToString();
|
||||
m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl);
|
||||
httpResponse.StatusCode = (int)OSHttpStatusCode.RedirectMovedPermanently;
|
||||
httpResponse.RedirectLocation = textureUrl;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -62,8 +62,10 @@ namespace OpenSim.Capabilities.Handlers
|
||||
if (m_AssetService == null)
|
||||
throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
|
||||
|
||||
string rurl = serverConfig.GetString("GetTextureRedirectURL");
|
||||
;
|
||||
server.AddStreamHandler(
|
||||
new GetTextureHandler("/CAPS/GetTexture/" /*+ UUID.Random() */, m_AssetService, "GetTexture", null));
|
||||
new GetTextureHandler("/CAPS/GetTexture/" /*+ UUID.Random() */, m_AssetService, "GetTexture", null, rurl));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
|
||||
// Overkill - we only really need the asset service, not a whole scene.
|
||||
Scene scene = new SceneHelpers().SetupScene();
|
||||
|
||||
GetTextureHandler handler = new GetTextureHandler(null, scene.AssetService, "TestGetTexture", null);
|
||||
GetTextureHandler handler = new GetTextureHandler(null, scene.AssetService, "TestGetTexture", null, null);
|
||||
TestOSHttpRequest req = new TestOSHttpRequest();
|
||||
TestOSHttpResponse resp = new TestOSHttpResponse();
|
||||
req.Url = new Uri("http://localhost/?texture_id=00000000-0000-1111-9999-000000000012");
|
||||
|
||||
+9
-1
@@ -238,7 +238,15 @@ namespace OpenSim.Capabilities.Handlers
|
||||
|
||||
if (folderID != UUID.Zero)
|
||||
{
|
||||
contents = m_InventoryService.GetFolderContent(agentID, folderID);
|
||||
InventoryCollection fetchedContents = m_InventoryService.GetFolderContent(agentID, folderID);
|
||||
|
||||
if (fetchedContents == null)
|
||||
{
|
||||
m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of folder {0} for user {1}", folderID, agentID);
|
||||
return contents;
|
||||
}
|
||||
|
||||
contents = fetchedContents;
|
||||
InventoryFolderBase containingFolder = new InventoryFolderBase();
|
||||
containingFolder.ID = folderID;
|
||||
containingFolder.Owner = agentID;
|
||||
|
||||
@@ -37,9 +37,8 @@ namespace OpenSim.Data
|
||||
public abstract class AssetDataBase : IAssetDataPlugin
|
||||
{
|
||||
public abstract AssetBase GetAsset(UUID uuid);
|
||||
|
||||
public abstract void StoreAsset(AssetBase asset);
|
||||
public abstract bool ExistsAsset(UUID uuid);
|
||||
public abstract bool[] AssetsExist(UUID[] uuids);
|
||||
|
||||
public abstract List<AssetMetadata> FetchAssetMetadataSet(int start, int count);
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace OpenSim.Data
|
||||
{
|
||||
AssetBase GetAsset(UUID uuid);
|
||||
void StoreAsset(AssetBase asset);
|
||||
bool ExistsAsset(UUID uuid);
|
||||
bool[] AssetsExist(UUID[] uuids);
|
||||
List<AssetMetadata> FetchAssetMetadataSet(int start, int count);
|
||||
void Initialise(string connect);
|
||||
bool Delete(string id);
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ using System.Collections.Generic;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
|
||||
namespace OpenSim.Region.Framework.Interfaces
|
||||
namespace OpenSim.Data
|
||||
{
|
||||
public interface IEstateDataStore
|
||||
{
|
||||
@@ -39,7 +39,7 @@ namespace OpenSim.Data
|
||||
{
|
||||
AssetBase GetAsset(UUID uuid);
|
||||
void StoreAsset(AssetBase asset);
|
||||
bool ExistsAsset(UUID uuid);
|
||||
bool[] AssetsExist(UUID[] uuids);
|
||||
List<AssetMetadata> FetchAssetMetadataSet(int start, int count);
|
||||
void Initialise(string connect);
|
||||
bool Delete(string id);
|
||||
|
||||
@@ -48,9 +48,57 @@ namespace OpenSim.Data
|
||||
public ulong everyonePowers;
|
||||
public ulong ownersPowers;
|
||||
|
||||
public Dictionary<UUID, XGroupMember> members = new Dictionary<UUID, XGroupMember>();
|
||||
public Dictionary<UUID, XGroupNotice> notices = new Dictionary<UUID, XGroupNotice>();
|
||||
|
||||
public XGroup Clone()
|
||||
{
|
||||
return (XGroup)MemberwiseClone();
|
||||
XGroup clone = (XGroup)MemberwiseClone();
|
||||
clone.members = new Dictionary<UUID, XGroupMember>();
|
||||
clone.notices = new Dictionary<UUID, XGroupNotice>();
|
||||
|
||||
foreach (KeyValuePair<UUID, XGroupMember> kvp in members)
|
||||
clone.members[kvp.Key] = kvp.Value.Clone();
|
||||
|
||||
foreach (KeyValuePair<UUID, XGroupNotice> kvp in notices)
|
||||
clone.notices[kvp.Key] = kvp.Value.Clone();
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
public class XGroupMember
|
||||
{
|
||||
public UUID agentID;
|
||||
public UUID groupID;
|
||||
public UUID roleID;
|
||||
public bool acceptNotices = true;
|
||||
public bool listInProfile = true;
|
||||
|
||||
public XGroupMember Clone()
|
||||
{
|
||||
return (XGroupMember)MemberwiseClone();
|
||||
}
|
||||
}
|
||||
|
||||
public class XGroupNotice
|
||||
{
|
||||
public UUID groupID;
|
||||
public UUID noticeID;
|
||||
public uint timestamp;
|
||||
public string fromName;
|
||||
public string subject;
|
||||
public string message;
|
||||
public byte[] binaryBucket;
|
||||
public bool hasAttachment;
|
||||
public int assetType;
|
||||
|
||||
public XGroupNotice Clone()
|
||||
{
|
||||
XGroupNotice clone = (XGroupNotice)MemberwiseClone();
|
||||
clone.binaryBucket = (byte[])binaryBucket.Clone();
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,14 +106,13 @@ namespace OpenSim.Data
|
||||
/// Early stub interface for groups data, not final.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Currently in-use only for regression test purposes. Needs to be filled out over time.
|
||||
/// Currently in-use only for regression test purposes.
|
||||
/// </remarks>
|
||||
public interface IXGroupData
|
||||
{
|
||||
bool StoreGroup(XGroup group);
|
||||
XGroup[] GetGroups(string field, string val);
|
||||
XGroup[] GetGroups(string[] fields, string[] vals);
|
||||
bool DeleteGroups(string field, string val);
|
||||
bool DeleteGroups(string[] fields, string[] vals);
|
||||
XGroup GetGroup(UUID groupID);
|
||||
Dictionary<UUID, XGroup> GetGroups();
|
||||
bool DeleteGroup(UUID groupID);
|
||||
}
|
||||
}
|
||||
@@ -160,18 +160,18 @@ namespace OpenSim.Data.MSSQL
|
||||
@temporary, @create_time, @access_time, @creatorid, @asset_flags, @data)";
|
||||
|
||||
string assetName = asset.Name;
|
||||
if (asset.Name.Length > 64)
|
||||
if (asset.Name.Length > AssetBase.MAX_ASSET_NAME)
|
||||
{
|
||||
assetName = asset.Name.Substring(0, 64);
|
||||
assetName = asset.Name.Substring(0, AssetBase.MAX_ASSET_NAME);
|
||||
m_log.WarnFormat(
|
||||
"[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",
|
||||
asset.Name, asset.ID, asset.Name.Length, assetName.Length);
|
||||
}
|
||||
|
||||
string assetDescription = asset.Description;
|
||||
if (asset.Description.Length > 64)
|
||||
if (asset.Description.Length > AssetBase.MAX_ASSET_DESC)
|
||||
{
|
||||
assetDescription = asset.Description.Substring(0, 64);
|
||||
assetDescription = asset.Description.Substring(0, AssetBase.MAX_ASSET_DESC);
|
||||
m_log.WarnFormat(
|
||||
"[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",
|
||||
asset.Description, asset.ID, asset.Description.Length, assetDescription.Length);
|
||||
@@ -225,17 +225,38 @@ namespace OpenSim.Data.MSSQL
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Check if asset exist in m_database
|
||||
/// Check if the assets exist in the database.
|
||||
/// </summary>
|
||||
/// <param name="uuid"></param>
|
||||
/// <returns>true if exist.</returns>
|
||||
override public bool ExistsAsset(UUID uuid)
|
||||
/// <param name="uuids">The assets' IDs</param>
|
||||
/// <returns>For each asset: true if it exists, false otherwise</returns>
|
||||
public override bool[] AssetsExist(UUID[] uuids)
|
||||
{
|
||||
if (GetAsset(uuid) != null)
|
||||
if (uuids.Length == 0)
|
||||
return new bool[0];
|
||||
|
||||
HashSet<UUID> exist = new HashSet<UUID>();
|
||||
|
||||
string ids = "'" + string.Join("','", uuids) + "'";
|
||||
string sql = string.Format("SELECT id FROM assets WHERE id IN ({0})", ids);
|
||||
|
||||
using (SqlConnection conn = new SqlConnection(m_connectionString))
|
||||
using (SqlCommand cmd = new SqlCommand(sql, conn))
|
||||
{
|
||||
return true;
|
||||
conn.Open();
|
||||
using (SqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
UUID id = DBGuid.FromDB(reader["id"]);
|
||||
exist.Add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
bool[] results = new bool[uuids.Length];
|
||||
for (int i = 0; i < uuids.Length; i++)
|
||||
results[i] = exist.Contains(uuids[i]);
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
@@ -55,7 +55,7 @@ namespace OpenSim.Data.MSSQL
|
||||
return Delete(principalID.ToString(), friend);
|
||||
}
|
||||
|
||||
public bool Delete(string principalID, string friend)
|
||||
public override bool Delete(string principalID, string friend)
|
||||
{
|
||||
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
|
||||
using (SqlCommand cmd = new SqlCommand())
|
||||
|
||||
@@ -278,7 +278,7 @@ namespace OpenSim.Data.MSSQL
|
||||
// m_log.DebugFormat("[MYSQL ITEM HANDLER]: Incrementing version on folder {0}", folderID);
|
||||
// Util.PrintCallStack();
|
||||
|
||||
string sql = "update inventoryfolders set version=version+1 where folderID = ?folderID";
|
||||
string sql = "update inventoryfolders set version=version+1 where folderID = @folderID";
|
||||
|
||||
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
|
||||
{
|
||||
|
||||
@@ -331,4 +331,12 @@ ALTER TABLE dbo.estate_map ADD CONSTRAINT
|
||||
|
||||
COMMIT
|
||||
|
||||
:VERSION 10
|
||||
|
||||
BEGIN transaction
|
||||
|
||||
ALTER TABLE estate_settings ADD AllowLandmark tinyint NOT NULL default 1;
|
||||
ALTER TABLE estate_settings ADD AllowParcelChanges tinyint NOT NULL default 1;
|
||||
ALTER TABLE estate_settings ADD AllowSetHome tinyint NOT NULL default 1;
|
||||
|
||||
COMMIT;
|
||||
@@ -1,4 +1,4 @@
|
||||
:VERSION 1
|
||||
:VERSION 1
|
||||
|
||||
BEGIN TRANSACTION
|
||||
|
||||
@@ -26,6 +26,14 @@ COMMIT
|
||||
|
||||
BEGIN TRANSACTION
|
||||
|
||||
ALTER TABLE Presence ADD LastSeen DateTime
|
||||
ALTER TABLE Presence ADD LastSeen DateTime;
|
||||
|
||||
COMMIT
|
||||
COMMIT
|
||||
|
||||
:VERSION 3
|
||||
|
||||
BEGIN TRANSACTION
|
||||
|
||||
CREATE INDEX RegionID ON Presence(RegionID);
|
||||
|
||||
COMMIT
|
||||
|
||||
@@ -1161,11 +1161,11 @@ COMMIT
|
||||
|
||||
BEGIN TRANSACTION
|
||||
|
||||
ALTER TABLE prims ADD `PhysicsShapeType` tinyint(4) NOT NULL default '0';
|
||||
ALTER TABLE prims ADD `Density` double NOT NULL default '1000';
|
||||
ALTER TABLE prims ADD `GravityModifier` double NOT NULL default '1';
|
||||
ALTER TABLE prims ADD `Friction` double NOT NULL default '0.6';
|
||||
ALTER TABLE prims ADD `Restitution` double NOT NULL default '0.5';
|
||||
ALTER TABLE prims ADD PhysicsShapeType tinyint NOT NULL default 0;
|
||||
ALTER TABLE prims ADD Density float NOT NULL default 1000;
|
||||
ALTER TABLE prims ADD GravityModifier float NOT NULL default 1;
|
||||
ALTER TABLE prims ADD Friction float NOT NULL default 0.6;
|
||||
ALTER TABLE prims ADD Restitution float NOT NULL default 0.5;
|
||||
|
||||
COMMIT
|
||||
|
||||
|
||||
@@ -171,18 +171,18 @@ namespace OpenSim.Data.MySQL
|
||||
dbcon))
|
||||
{
|
||||
string assetName = asset.Name;
|
||||
if (asset.Name.Length > 64)
|
||||
if (asset.Name.Length > AssetBase.MAX_ASSET_NAME)
|
||||
{
|
||||
assetName = asset.Name.Substring(0, 64);
|
||||
assetName = asset.Name.Substring(0, AssetBase.MAX_ASSET_NAME);
|
||||
m_log.WarnFormat(
|
||||
"[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",
|
||||
asset.Name, asset.ID, asset.Name.Length, assetName.Length);
|
||||
}
|
||||
|
||||
string assetDescription = asset.Description;
|
||||
if (asset.Description.Length > 64)
|
||||
if (asset.Description.Length > AssetBase.MAX_ASSET_DESC)
|
||||
{
|
||||
assetDescription = asset.Description.Substring(0, 64);
|
||||
assetDescription = asset.Description.Substring(0, AssetBase.MAX_ASSET_DESC);
|
||||
m_log.WarnFormat(
|
||||
"[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",
|
||||
asset.Description, asset.ID, asset.Description.Length, assetDescription.Length);
|
||||
@@ -257,46 +257,44 @@ namespace OpenSim.Data.MySQL
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the asset exists in the database
|
||||
/// Check if the assets exist in the database.
|
||||
/// </summary>
|
||||
/// <param name="uuid">The asset UUID</param>
|
||||
/// <returns>true if it exists, false otherwise.</returns>
|
||||
override public bool ExistsAsset(UUID uuid)
|
||||
/// <param name="uuidss">The assets' IDs</param>
|
||||
/// <returns>For each asset: true if it exists, false otherwise</returns>
|
||||
public override bool[] AssetsExist(UUID[] uuids)
|
||||
{
|
||||
// m_log.DebugFormat("[ASSETS DB]: Checking for asset {0}", uuid);
|
||||
if (uuids.Length == 0)
|
||||
return new bool[0];
|
||||
|
||||
bool assetExists = false;
|
||||
HashSet<UUID> exist = new HashSet<UUID>();
|
||||
|
||||
string ids = "'" + string.Join("','", uuids) + "'";
|
||||
string sql = string.Format("SELECT id FROM assets WHERE id IN ({0})", ids);
|
||||
|
||||
lock (m_dbLock)
|
||||
{
|
||||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
{
|
||||
dbcon.Open();
|
||||
using (MySqlCommand cmd = new MySqlCommand("SELECT id FROM assets WHERE id=?id", dbcon))
|
||||
using (MySqlCommand cmd = new MySqlCommand(sql, dbcon))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("?id", uuid.ToString());
|
||||
|
||||
try
|
||||
using (MySqlDataReader dbReader = cmd.ExecuteReader())
|
||||
{
|
||||
using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
|
||||
while (dbReader.Read())
|
||||
{
|
||||
if (dbReader.Read())
|
||||
{
|
||||
// m_log.DebugFormat("[ASSETS DB]: Found asset {0}", uuid);
|
||||
assetExists = true;
|
||||
}
|
||||
UUID id = DBGuid.FromDB(dbReader["id"]);
|
||||
exist.Add(id);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error(
|
||||
string.Format("[ASSETS DB]: MySql failure fetching asset {0}. Exception ", uuid), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return assetExists;
|
||||
bool[] results = new bool[uuids.Length];
|
||||
for (int i = 0; i < uuids.Length; i++)
|
||||
results[i] = exist.Contains(uuids[i]);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -145,7 +145,11 @@ namespace OpenSim.Data.MySQL
|
||||
cmd.CommandText = sql;
|
||||
cmd.Parameters.AddWithValue("?RegionID", regionID.ToString());
|
||||
|
||||
return DoLoad(cmd, regionID, create);
|
||||
EstateSettings e = DoLoad(cmd, regionID, create);
|
||||
if (!create && e.EstateID == 0) // Not found
|
||||
return null;
|
||||
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,7 +431,10 @@ namespace OpenSim.Data.MySQL
|
||||
cmd.CommandText = sql;
|
||||
cmd.Parameters.AddWithValue("?EstateID", estateID);
|
||||
|
||||
return DoLoad(cmd, UUID.Zero, false);
|
||||
EstateSettings e = DoLoad(cmd, UUID.Zero, false);
|
||||
if (e.EstateID != estateID)
|
||||
return null;
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace OpenSim.Data.MySQL
|
||||
return Delete(principalID.ToString(), friend);
|
||||
}
|
||||
|
||||
public bool Delete(string principalID, string friend)
|
||||
public override bool Delete(string principalID, string friend)
|
||||
{
|
||||
using (MySqlCommand cmd = new MySqlCommand())
|
||||
{
|
||||
|
||||
@@ -86,11 +86,11 @@ namespace OpenSim.Data.MySQL
|
||||
public GroupData[] RetrieveGroups(string pattern)
|
||||
{
|
||||
if (string.IsNullOrEmpty(pattern))
|
||||
pattern = "1 ORDER BY Name LIMIT 100";
|
||||
pattern = "1";
|
||||
else
|
||||
pattern = string.Format("Name LIKE '%{0}%' ORDER BY Name LIMIT 100", pattern);
|
||||
pattern = string.Format("Name LIKE '%{0}%'", MySqlHelper.EscapeString(pattern));
|
||||
|
||||
return m_Groups.Get(pattern);
|
||||
return m_Groups.Get(string.Format("ShowInList=1 AND ({0}) ORDER BY Name LIMIT 100", pattern));
|
||||
}
|
||||
|
||||
public bool DeleteGroup(UUID groupID)
|
||||
|
||||
@@ -695,7 +695,7 @@ namespace OpenSim.Data.MySQL
|
||||
"MusicURL, PassHours, PassPrice, SnapshotUUID, " +
|
||||
"UserLocationX, UserLocationY, UserLocationZ, " +
|
||||
"UserLookAtX, UserLookAtY, UserLookAtZ, " +
|
||||
"AuthbuyerID, OtherCleanTime, MediaType, MediaDescription, " +
|
||||
"AuthbuyerID, OtherCleanTime, Dwell, MediaType, MediaDescription, " +
|
||||
"MediaSize, MediaLoop, ObscureMusic, ObscureMedia) values (" +
|
||||
"?UUID, ?RegionUUID, " +
|
||||
"?LocalLandID, ?Bitmap, ?Name, ?Description, " +
|
||||
@@ -706,7 +706,7 @@ namespace OpenSim.Data.MySQL
|
||||
"?MusicURL, ?PassHours, ?PassPrice, ?SnapshotUUID, " +
|
||||
"?UserLocationX, ?UserLocationY, ?UserLocationZ, " +
|
||||
"?UserLookAtX, ?UserLookAtY, ?UserLookAtZ, " +
|
||||
"?AuthbuyerID, ?OtherCleanTime, ?MediaType, ?MediaDescription, "+
|
||||
"?AuthbuyerID, ?OtherCleanTime, ?Dwell, ?MediaType, ?MediaDescription, "+
|
||||
"CONCAT(?MediaWidth, ',', ?MediaHeight), ?MediaLoop, ?ObscureMusic, ?ObscureMedia)";
|
||||
|
||||
FillLandCommand(cmd, parcel.LandData, parcel.RegionUUID);
|
||||
@@ -1484,6 +1484,7 @@ namespace OpenSim.Data.MySQL
|
||||
UUID.TryParse((string)row["AuthBuyerID"], out authedbuyer);
|
||||
UUID.TryParse((string)row["SnapshotUUID"], out snapshotID);
|
||||
newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]);
|
||||
newData.Dwell = Convert.ToSingle(row["Dwell"]);
|
||||
|
||||
newData.AuthBuyerID = authedbuyer;
|
||||
newData.SnapshotID = snapshotID;
|
||||
@@ -1815,6 +1816,7 @@ namespace OpenSim.Data.MySQL
|
||||
cmd.Parameters.AddWithValue("UserLookAtZ", land.UserLookAt.Z);
|
||||
cmd.Parameters.AddWithValue("AuthBuyerID", land.AuthBuyerID);
|
||||
cmd.Parameters.AddWithValue("OtherCleanTime", land.OtherCleanTime);
|
||||
cmd.Parameters.AddWithValue("Dwell", land.Dwell);
|
||||
cmd.Parameters.AddWithValue("MediaDescription", land.MediaDescription);
|
||||
cmd.Parameters.AddWithValue("MediaType", land.MediaType);
|
||||
cmd.Parameters.AddWithValue("MediaWidth", land.MediaWidth);
|
||||
@@ -1822,7 +1824,6 @@ namespace OpenSim.Data.MySQL
|
||||
cmd.Parameters.AddWithValue("MediaLoop", land.MediaLoop);
|
||||
cmd.Parameters.AddWithValue("ObscureMusic", land.ObscureMusic);
|
||||
cmd.Parameters.AddWithValue("ObscureMedia", land.ObscureMedia);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -634,8 +634,6 @@ namespace OpenSim.Data.MySQL
|
||||
{
|
||||
if(reader.HasRows)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": Getting data for {0}.", props.UserId);
|
||||
reader.Read();
|
||||
props.WebUrl = (string)reader["profileURL"];
|
||||
UUID.TryParse((string)reader["profileImage"], out props.ImageId);
|
||||
@@ -651,9 +649,6 @@ namespace OpenSim.Data.MySQL
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": No data for {0}", props.UserId);
|
||||
|
||||
props.WebUrl = string.Empty;
|
||||
props.ImageId = UUID.Zero;
|
||||
props.AboutText = string.Empty;
|
||||
@@ -974,8 +969,8 @@ namespace OpenSim.Data.MySQL
|
||||
dbcon.Open();
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("?ImViaEmail", pref.IMViaEmail);
|
||||
cmd.Parameters.AddWithValue("?Visible", pref.Visible);
|
||||
cmd.Parameters.AddWithValue("?ImViaEmail", pref.IMViaEmail.ToString().ToLower());
|
||||
cmd.Parameters.AddWithValue("?Visible", pref.Visible.ToString().ToLower());
|
||||
cmd.Parameters.AddWithValue("?uuid", pref.UserId.ToString());
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
|
||||
@@ -210,18 +210,18 @@ namespace OpenSim.Data.MySQL
|
||||
using (MySqlTransaction transaction = dbcon.BeginTransaction())
|
||||
{
|
||||
string assetName = asset.Name;
|
||||
if (asset.Name.Length > 64)
|
||||
if (asset.Name.Length > AssetBase.MAX_ASSET_NAME)
|
||||
{
|
||||
assetName = asset.Name.Substring(0, 64);
|
||||
assetName = asset.Name.Substring(0, AssetBase.MAX_ASSET_NAME);
|
||||
m_log.WarnFormat(
|
||||
"[XASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",
|
||||
asset.Name, asset.ID, asset.Name.Length, assetName.Length);
|
||||
}
|
||||
|
||||
string assetDescription = asset.Description;
|
||||
if (asset.Description.Length > 64)
|
||||
if (asset.Description.Length > AssetBase.MAX_ASSET_DESC)
|
||||
{
|
||||
assetDescription = asset.Description.Substring(0, 64);
|
||||
assetDescription = asset.Description.Substring(0, AssetBase.MAX_ASSET_DESC);
|
||||
m_log.WarnFormat(
|
||||
"[XASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",
|
||||
asset.Description, asset.ID, asset.Description.Length, assetDescription.Length);
|
||||
@@ -346,7 +346,7 @@ namespace OpenSim.Data.MySQL
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[XASSET MYSQL DB]: Failure updating access_time for asset {0} with name {1}",
|
||||
@@ -397,45 +397,43 @@ namespace OpenSim.Data.MySQL
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the asset exists in the database
|
||||
/// Check if the assets exist in the database.
|
||||
/// </summary>
|
||||
/// <param name="uuid">The asset UUID</param>
|
||||
/// <returns>true if it exists, false otherwise.</returns>
|
||||
public bool ExistsAsset(UUID uuid)
|
||||
/// <param name="uuids">The asset UUID's</param>
|
||||
/// <returns>For each asset: true if it exists, false otherwise</returns>
|
||||
public bool[] AssetsExist(UUID[] uuids)
|
||||
{
|
||||
// m_log.DebugFormat("[ASSETS DB]: Checking for asset {0}", uuid);
|
||||
if (uuids.Length == 0)
|
||||
return new bool[0];
|
||||
|
||||
bool assetExists = false;
|
||||
HashSet<UUID> exists = new HashSet<UUID>();
|
||||
|
||||
string ids = "'" + string.Join("','", uuids) + "'";
|
||||
string sql = string.Format("SELECT ID FROM assets WHERE ID IN ({0})", ids);
|
||||
|
||||
lock (m_dbLock)
|
||||
{
|
||||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
{
|
||||
dbcon.Open();
|
||||
using (MySqlCommand cmd = new MySqlCommand("SELECT ID FROM XAssetsMeta WHERE ID=?ID", dbcon))
|
||||
using (MySqlCommand cmd = new MySqlCommand(sql, dbcon))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("?ID", uuid.ToString());
|
||||
|
||||
try
|
||||
using (MySqlDataReader dbReader = cmd.ExecuteReader())
|
||||
{
|
||||
using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
|
||||
while (dbReader.Read())
|
||||
{
|
||||
if (dbReader.Read())
|
||||
{
|
||||
// m_log.DebugFormat("[ASSETS DB]: Found asset {0}", uuid);
|
||||
assetExists = true;
|
||||
}
|
||||
UUID id = DBGuid.FromDB(dbReader["ID"]);
|
||||
exists.Add(id);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error(string.Format("[XASSETS DB]: MySql failure fetching asset {0}", uuid), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return assetExists;
|
||||
bool[] results = new bool[uuids.Length];
|
||||
for (int i = 0; i < uuids.Length; i++)
|
||||
results[i] = exists.Contains(uuids[i]);
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:VERSION 1 # --------------------------
|
||||
:VERSION 1 # --------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
@@ -32,3 +32,11 @@ ALTER TABLE `im_offline`
|
||||
ADD KEY `FromID` (`FromID`);
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 4 # --------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE im_offline CONVERT TO CHARACTER SET utf8;
|
||||
|
||||
COMMIT;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:VERSION 1 # --------------------------
|
||||
:VERSION 1 # --------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
@@ -21,3 +21,11 @@ BEGIN;
|
||||
ALTER TABLE `Presence` ADD COLUMN LastSeen timestamp;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 3 # --------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE INDEX RegionID ON Presence(RegionID);
|
||||
|
||||
COMMIT;
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace OpenSim.Data.Null
|
||||
|
||||
// private string m_connectionString;
|
||||
|
||||
private Dictionary<uint, EstateSettings> m_knownEstates = new Dictionary<uint, EstateSettings>();
|
||||
// private Dictionary<uint, EstateSettings> m_knownEstates = new Dictionary<uint, EstateSettings>();
|
||||
private EstateSettings m_estate = null;
|
||||
|
||||
private EstateSettings GetEstate()
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace OpenSim.Data.Null
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private static NullPresenceData Instance;
|
||||
public static NullPresenceData Instance;
|
||||
|
||||
Dictionary<UUID, PresenceData> m_presenceData = new Dictionary<UUID, PresenceData>();
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ using OpenSim.Data;
|
||||
|
||||
namespace OpenSim.Data.Null
|
||||
{
|
||||
public class NullXGroupData : NullGenericDataHandler, IXGroupData
|
||||
public class NullXGroupData : IXGroupData
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
@@ -56,35 +56,31 @@ namespace OpenSim.Data.Null
|
||||
return true;
|
||||
}
|
||||
|
||||
public XGroup[] GetGroups(string field, string val)
|
||||
public XGroup GetGroup(UUID groupID)
|
||||
{
|
||||
return GetGroups(new string[] { field }, new string[] { val });
|
||||
XGroup group = null;
|
||||
|
||||
lock (m_groups)
|
||||
m_groups.TryGetValue(groupID, out group);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
public XGroup[] GetGroups(string[] fields, string[] vals)
|
||||
public Dictionary<UUID, XGroup> GetGroups()
|
||||
{
|
||||
Dictionary<UUID, XGroup> groupsClone = new Dictionary<UUID, XGroup>();
|
||||
|
||||
lock (m_groups)
|
||||
foreach (XGroup group in m_groups.Values)
|
||||
groupsClone[group.groupID] = group.Clone();
|
||||
|
||||
return groupsClone;
|
||||
}
|
||||
|
||||
public bool DeleteGroup(UUID groupID)
|
||||
{
|
||||
lock (m_groups)
|
||||
{
|
||||
List<XGroup> origGroups = Get<XGroup>(fields, vals, m_groups.Values.ToList());
|
||||
|
||||
return origGroups.Select(g => g.Clone()).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public bool DeleteGroups(string field, string val)
|
||||
{
|
||||
return DeleteGroups(new string[] { field }, new string[] { val });
|
||||
}
|
||||
|
||||
public bool DeleteGroups(string[] fields, string[] vals)
|
||||
{
|
||||
lock (m_groups)
|
||||
{
|
||||
XGroup[] groupsToDelete = GetGroups(fields, vals);
|
||||
Array.ForEach(groupsToDelete, g => m_groups.Remove(g.groupID));
|
||||
}
|
||||
|
||||
return true;
|
||||
return m_groups.Remove(groupID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,18 +166,18 @@ namespace OpenSim.Data.PGSQL
|
||||
";
|
||||
|
||||
string assetName = asset.Name;
|
||||
if (asset.Name.Length > 64)
|
||||
if (asset.Name.Length > AssetBase.MAX_ASSET_NAME)
|
||||
{
|
||||
assetName = asset.Name.Substring(0, 64);
|
||||
assetName = asset.Name.Substring(0, AssetBase.MAX_ASSET_NAME);
|
||||
m_log.WarnFormat(
|
||||
"[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",
|
||||
asset.Name, asset.ID, asset.Name.Length, assetName.Length);
|
||||
}
|
||||
|
||||
string assetDescription = asset.Description;
|
||||
if (asset.Description.Length > 64)
|
||||
if (asset.Description.Length > AssetBase.MAX_ASSET_DESC)
|
||||
{
|
||||
assetDescription = asset.Description.Substring(0, 64);
|
||||
assetDescription = asset.Description.Substring(0, AssetBase.MAX_ASSET_DESC);
|
||||
m_log.WarnFormat(
|
||||
"[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",
|
||||
asset.Description, asset.ID, asset.Description.Length, assetDescription.Length);
|
||||
@@ -231,17 +231,38 @@ namespace OpenSim.Data.PGSQL
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Check if asset exist in m_database
|
||||
/// Check if the assets exist in the database.
|
||||
/// </summary>
|
||||
/// <param name="uuid"></param>
|
||||
/// <returns>true if exist.</returns>
|
||||
override public bool ExistsAsset(UUID uuid)
|
||||
/// <param name="uuids">The assets' IDs</param>
|
||||
/// <returns>For each asset: true if it exists, false otherwise</returns>
|
||||
public override bool[] AssetsExist(UUID[] uuids)
|
||||
{
|
||||
if (GetAsset(uuid) != null)
|
||||
if (uuids.Length == 0)
|
||||
return new bool[0];
|
||||
|
||||
HashSet<UUID> exist = new HashSet<UUID>();
|
||||
|
||||
string ids = "'" + string.Join("','", uuids) + "'";
|
||||
string sql = string.Format("SELECT id FROM assets WHERE id IN ({0})", ids);
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
return true;
|
||||
conn.Open();
|
||||
using (NpgsqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
UUID id = DBGuid.FromDB(reader["id"]);
|
||||
exist.Add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
bool[] results = new bool[uuids.Length];
|
||||
for (int i = 0; i < uuids.Length; i++)
|
||||
results[i] = exist.Contains(uuids[i]);
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace OpenSim.Data.PGSQL
|
||||
}
|
||||
|
||||
|
||||
public bool Delete(string principalID, string friend)
|
||||
public override bool Delete(string principalID, string friend)
|
||||
{
|
||||
UUID princUUID = UUID.Zero;
|
||||
|
||||
|
||||
@@ -300,7 +300,6 @@ namespace OpenSim.Data.PGSQL
|
||||
m_Realm, where);
|
||||
cmd.Connection = conn;
|
||||
cmd.CommandText = query;
|
||||
|
||||
//m_log.WarnFormat("[PGSQLGenericTable]: SELECT {0} WHERE {1}", m_Realm, where);
|
||||
|
||||
conn.Open();
|
||||
@@ -308,6 +307,25 @@ namespace OpenSim.Data.PGSQL
|
||||
}
|
||||
}
|
||||
|
||||
public virtual T[] Get(string where, NpgsqlParameter parameter)
|
||||
{
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
|
||||
string query = String.Format("SELECT * FROM {0} WHERE {1}",
|
||||
m_Realm, where);
|
||||
cmd.Connection = conn;
|
||||
cmd.CommandText = query;
|
||||
//m_log.WarnFormat("[PGSQLGenericTable]: SELECT {0} WHERE {1}", m_Realm, where);
|
||||
|
||||
cmd.Parameters.Add(parameter);
|
||||
|
||||
conn.Open();
|
||||
return DoQuery(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool Store(T row)
|
||||
{
|
||||
List<string> constraintFields = GetConstraints();
|
||||
|
||||
@@ -83,11 +83,15 @@ namespace OpenSim.Data.PGSQL
|
||||
public GroupData[] RetrieveGroups(string pattern)
|
||||
{
|
||||
if (string.IsNullOrEmpty(pattern)) // True for where clause
|
||||
{
|
||||
pattern = " true ORDER BY lower(\"Name\") LIMIT 100";
|
||||
return m_Groups.Get(pattern);
|
||||
}
|
||||
else
|
||||
pattern = string.Format(" lower(\"Name\") LIKE lower('%{0}%') ORDER BY lower(\"Name\") LIMIT 100", pattern);
|
||||
|
||||
return m_Groups.Get(pattern);
|
||||
{
|
||||
pattern = " lower(\"Name\") LIKE lower('%:pattern%') ORDER BY lower(\"Name\") LIMIT 100";
|
||||
return m_Groups.Get(pattern, new NpgsqlParameter("pattern", pattern));
|
||||
}
|
||||
}
|
||||
|
||||
public bool DeleteGroup(UUID groupID)
|
||||
|
||||
@@ -406,6 +406,43 @@ namespace OpenSim.Data.PGSQL
|
||||
return exists;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the assets exist in the database.
|
||||
/// </summary>
|
||||
/// <param name="uuids">The assets' IDs</param>
|
||||
/// <returns>For each asset: true if it exists, false otherwise</returns>
|
||||
public bool[] AssetsExist(UUID[] uuids)
|
||||
{
|
||||
if (uuids.Length == 0)
|
||||
return new bool[0];
|
||||
|
||||
HashSet<UUID> exist = new HashSet<UUID>();
|
||||
|
||||
string ids = "'" + string.Join("','", uuids) + "'";
|
||||
string sql = string.Format(@"SELECT ""ID"" FROM XAssetsMeta WHERE ""ID"" IN ({0})", ids);
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
conn.Open();
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
using (NpgsqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
UUID id = DBGuid.FromDB(reader["id"]);
|
||||
exist.Add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool[] results = new bool[uuids.Length];
|
||||
for (int i = 0; i < uuids.Length; i++)
|
||||
results[i] = exist.Contains(uuids[i]);
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the asset exists in the database
|
||||
/// </summary>
|
||||
|
||||
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly : AssemblyVersion("0.7.6.*")]
|
||||
[assembly : AssemblyVersion("0.8.0.*")]
|
||||
|
||||
|
||||
@@ -134,25 +134,25 @@ namespace OpenSim.Data.SQLite
|
||||
override public void StoreAsset(AssetBase asset)
|
||||
{
|
||||
string assetName = asset.Name;
|
||||
if (asset.Name.Length > 64)
|
||||
if (asset.Name.Length > AssetBase.MAX_ASSET_NAME)
|
||||
{
|
||||
assetName = asset.Name.Substring(0, 64);
|
||||
assetName = asset.Name.Substring(0, AssetBase.MAX_ASSET_NAME);
|
||||
m_log.WarnFormat(
|
||||
"[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",
|
||||
asset.Name, asset.ID, asset.Name.Length, assetName.Length);
|
||||
}
|
||||
|
||||
string assetDescription = asset.Description;
|
||||
if (asset.Description.Length > 64)
|
||||
if (asset.Description.Length > AssetBase.MAX_ASSET_DESC)
|
||||
{
|
||||
assetDescription = asset.Description.Substring(0, 64);
|
||||
assetDescription = asset.Description.Substring(0, AssetBase.MAX_ASSET_DESC);
|
||||
m_log.WarnFormat(
|
||||
"[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",
|
||||
asset.Description, asset.ID, asset.Description.Length, assetDescription.Length);
|
||||
}
|
||||
|
||||
//m_log.Info("[ASSET DB]: Creating Asset " + asset.FullID.ToString());
|
||||
if (ExistsAsset(asset.FullID))
|
||||
if (AssetsExist(new[] { asset.FullID })[0])
|
||||
{
|
||||
//LogAssetLoad(asset);
|
||||
|
||||
@@ -214,32 +214,39 @@ namespace OpenSim.Data.SQLite
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Check if an asset exist in database
|
||||
/// Check if the assets exist in the database.
|
||||
/// </summary>
|
||||
/// <param name="uuid">The asset UUID</param>
|
||||
/// <returns>True if exist, or false.</returns>
|
||||
override public bool ExistsAsset(UUID uuid)
|
||||
/// <param name="uuids">The assets' IDs</param>
|
||||
/// <returns>For each asset: true if it exists, false otherwise</returns>
|
||||
public override bool[] AssetsExist(UUID[] uuids)
|
||||
{
|
||||
lock (this)
|
||||
if (uuids.Length == 0)
|
||||
return new bool[0];
|
||||
|
||||
HashSet<UUID> exist = new HashSet<UUID>();
|
||||
|
||||
string ids = "'" + string.Join("','", uuids) + "'";
|
||||
string sql = string.Format("select UUID from assets where UUID in ({0})", ids);
|
||||
|
||||
lock (this)
|
||||
{
|
||||
using (SqliteCommand cmd = new SqliteCommand(SelectAssetSQL, m_conn))
|
||||
using (SqliteCommand cmd = new SqliteCommand(sql, m_conn))
|
||||
{
|
||||
cmd.Parameters.Add(new SqliteParameter(":UUID", uuid.ToString()));
|
||||
using (IDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
if (reader.Read())
|
||||
while (reader.Read())
|
||||
{
|
||||
reader.Close();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.Close();
|
||||
return false;
|
||||
UUID id = new UUID((string)reader["UUID"]);
|
||||
exist.Add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool[] results = new bool[uuids.Length];
|
||||
for (int i = 0; i < uuids.Length; i++)
|
||||
results[i] = exist.Contains(uuids[i]);
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace OpenSim.Data.SQLite
|
||||
return Delete(principalID.ToString(), friend);
|
||||
}
|
||||
|
||||
public bool Delete(string principalID, string friend)
|
||||
public override bool Delete(string principalID, string friend)
|
||||
{
|
||||
using (SqliteCommand cmd = new SqliteCommand())
|
||||
{
|
||||
|
||||
@@ -1605,7 +1605,7 @@ namespace OpenSim.Data.SQLite
|
||||
prim.SitName = (String)row["SitName"];
|
||||
prim.TouchName = (String)row["TouchName"];
|
||||
// permissions
|
||||
prim.ObjectFlags = Convert.ToUInt32(row["ObjectFlags"]);
|
||||
prim.Flags = (PrimFlags)Convert.ToUInt32(row["ObjectFlags"]);
|
||||
prim.CreatorIdentification = (String)row["CreatorID"];
|
||||
prim.OwnerID = new UUID((String)row["OwnerID"]);
|
||||
prim.GroupID = new UUID((String)row["GroupID"]);
|
||||
@@ -2034,7 +2034,7 @@ namespace OpenSim.Data.SQLite
|
||||
row["SitName"] = prim.SitName;
|
||||
row["TouchName"] = prim.TouchName;
|
||||
// permissions
|
||||
row["ObjectFlags"] = prim.ObjectFlags;
|
||||
row["ObjectFlags"] = (uint)prim.Flags;
|
||||
row["CreatorID"] = prim.CreatorIdentification.ToString();
|
||||
row["OwnerID"] = prim.OwnerID.ToString();
|
||||
row["GroupID"] = prim.GroupID.ToString();
|
||||
|
||||
@@ -50,7 +50,6 @@ namespace OpenSim.Data.SQLite
|
||||
private SqliteConnection m_connection;
|
||||
private string m_connectionString;
|
||||
|
||||
private FieldInfo[] m_Fields;
|
||||
private Dictionary<string, FieldInfo> m_FieldMap =
|
||||
new Dictionary<string, FieldInfo>();
|
||||
|
||||
@@ -585,9 +584,6 @@ namespace OpenSim.Data.SQLite
|
||||
}
|
||||
if(reader != null && reader.Read())
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": Getting data for {0}.", props.UserId);
|
||||
|
||||
props.WebUrl = (string)reader["profileURL"];
|
||||
UUID.TryParse((string)reader["profileImage"], out props.ImageId);
|
||||
props.AboutText = (string)reader["profileAboutText"];
|
||||
@@ -602,9 +598,6 @@ namespace OpenSim.Data.SQLite
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": No data for {0}", props.UserId);
|
||||
|
||||
props.WebUrl = string.Empty;
|
||||
props.ImageId = UUID.Zero;
|
||||
props.AboutText = string.Empty;
|
||||
|
||||
@@ -107,10 +107,11 @@ namespace OpenSim.Data.Tests
|
||||
public void T001_LoadEmpty()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
|
||||
Assert.That(m_db.ExistsAsset(uuid1), Is.False);
|
||||
Assert.That(m_db.ExistsAsset(uuid2), Is.False);
|
||||
Assert.That(m_db.ExistsAsset(uuid3), Is.False);
|
||||
|
||||
bool[] exist = m_db.AssetsExist(new[] { uuid1, uuid2, uuid3 });
|
||||
Assert.IsFalse(exist[0]);
|
||||
Assert.IsFalse(exist[1]);
|
||||
Assert.IsFalse(exist[2]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -159,9 +160,10 @@ namespace OpenSim.Data.Tests
|
||||
AssetBase a3b = m_db.GetAsset(uuid3);
|
||||
Assert.That(a3b, Constraints.PropertyCompareConstraint(a3a));
|
||||
|
||||
Assert.That(m_db.ExistsAsset(uuid1), Is.True);
|
||||
Assert.That(m_db.ExistsAsset(uuid2), Is.True);
|
||||
Assert.That(m_db.ExistsAsset(uuid3), Is.True);
|
||||
bool[] exist = m_db.AssetsExist(new[] { uuid1, uuid2, uuid3 });
|
||||
Assert.IsTrue(exist[0]);
|
||||
Assert.IsTrue(exist[1]);
|
||||
Assert.IsTrue(exist[2]);
|
||||
|
||||
List<AssetMetadata> metadatas = m_db.FetchAssetMetadataSet(0, 1000);
|
||||
|
||||
|
||||
@@ -99,6 +99,9 @@ namespace OpenSim.Data.Tests
|
||||
if (Directory.Exists("/proc/ppc64") || Directory.Exists("/proc/dasd"))
|
||||
Assert.Ignore();
|
||||
|
||||
if (Util.IsWindows())
|
||||
Util.LoadArchSpecificWindowsDll("sqlite3.dll");
|
||||
|
||||
// for SQLite, if no explicit conn string is specified, use a temp file
|
||||
if (String.IsNullOrEmpty(m_connStr))
|
||||
{
|
||||
|
||||
@@ -321,6 +321,8 @@ namespace OpenSim.Framework
|
||||
Mac = args["mac"].AsString();
|
||||
if (args["id0"] != null)
|
||||
Id0 = args["id0"].AsString();
|
||||
if (args["teleport_flags"] != null)
|
||||
teleportFlags = args["teleport_flags"].AsUInteger();
|
||||
|
||||
if (args["start_pos"] != null)
|
||||
Vector3.TryParse(args["start_pos"].AsString(), out startpos);
|
||||
|
||||
@@ -132,6 +132,11 @@ namespace OpenSim.Framework
|
||||
return base.Equals(obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "AnimID=" + AnimID.ToString()
|
||||
|
||||
@@ -50,6 +50,9 @@ namespace OpenSim.Framework
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public static readonly int MAX_ASSET_NAME = 64;
|
||||
public static readonly int MAX_ASSET_DESC = 64;
|
||||
|
||||
/// <summary>
|
||||
/// Data of the Asset
|
||||
/// </summary>
|
||||
|
||||
@@ -98,11 +98,11 @@ namespace OpenSim.Framework
|
||||
/// </remarks>
|
||||
public bool Contains(T item)
|
||||
{
|
||||
if (m_queue.Count < 1 && m_pqueue.Count < 1)
|
||||
return false;
|
||||
|
||||
lock (m_queueSync)
|
||||
{
|
||||
if (m_queue.Count < 1 && m_pqueue.Count < 1)
|
||||
return false;
|
||||
|
||||
if (m_pqueue.Contains(item))
|
||||
return true;
|
||||
return m_queue.Contains(item);
|
||||
@@ -112,12 +112,10 @@ namespace OpenSim.Framework
|
||||
/// <summary>
|
||||
/// Return a count of the number of requests on this queue.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method is not thread-safe. Do not rely on the result without consistent external locking.
|
||||
/// </remarks>
|
||||
public int Count()
|
||||
{
|
||||
return m_queue.Count + m_pqueue.Count;
|
||||
lock (m_queueSync)
|
||||
return m_queue.Count + m_pqueue.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -128,11 +126,11 @@ namespace OpenSim.Framework
|
||||
/// </remarks>
|
||||
public T[] GetQueueArray()
|
||||
{
|
||||
if (m_queue.Count < 1 && m_pqueue.Count < 1)
|
||||
return new T[0];
|
||||
|
||||
lock (m_queueSync)
|
||||
{
|
||||
if (m_queue.Count < 1 && m_pqueue.Count < 1)
|
||||
return new T[0];
|
||||
|
||||
return m_queue.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ using System.Threading;
|
||||
using System.Web;
|
||||
using log4net;
|
||||
|
||||
using OpenSim.Framework.ServiceAuth;
|
||||
|
||||
namespace OpenSim.Framework.Communications
|
||||
{
|
||||
/// <summary>
|
||||
@@ -298,6 +300,14 @@ namespace OpenSim.Framework.Communications
|
||||
/// Perform a synchronous request
|
||||
/// </summary>
|
||||
public Stream Request()
|
||||
{
|
||||
return Request(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform a synchronous request
|
||||
/// </summary>
|
||||
public Stream Request(IServiceAuth auth)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
@@ -307,6 +317,8 @@ namespace OpenSim.Framework.Communications
|
||||
_request.Timeout = 200000;
|
||||
_request.Method = RequestMethod;
|
||||
_asyncException = null;
|
||||
if (auth != null)
|
||||
auth.AddAuthorization(_request.Headers);
|
||||
|
||||
// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request);
|
||||
try
|
||||
@@ -318,12 +330,12 @@ namespace OpenSim.Framework.Communications
|
||||
HttpWebResponse errorResponse = e.Response as HttpWebResponse;
|
||||
if (null != errorResponse && HttpStatusCode.NotFound == errorResponse.StatusCode)
|
||||
{
|
||||
m_log.Warn("[REST CLIENT] Resource not found (404)");
|
||||
// This is often benign. E.g., requesting a missing asset will return 404.
|
||||
m_log.DebugFormat("[REST CLIENT] Resource not found (404): {0}", _request.Address.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Error("[REST CLIENT] Error fetching resource from server " + _request.Address.ToString());
|
||||
m_log.Debug(e.ToString());
|
||||
m_log.Error(string.Format("[REST CLIENT] Error fetching resource from server: {0} ", _request.Address.ToString()), e);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -358,7 +370,7 @@ namespace OpenSim.Framework.Communications
|
||||
}
|
||||
}
|
||||
|
||||
public Stream Request(Stream src)
|
||||
public Stream Request(Stream src, IServiceAuth auth)
|
||||
{
|
||||
_request = (HttpWebRequest) WebRequest.Create(buildUri());
|
||||
_request.KeepAlive = false;
|
||||
@@ -367,6 +379,8 @@ namespace OpenSim.Framework.Communications
|
||||
_request.Method = RequestMethod;
|
||||
_asyncException = null;
|
||||
_request.ContentLength = src.Length;
|
||||
if (auth != null)
|
||||
auth.AddAuthorization(_request.Headers);
|
||||
|
||||
m_log.InfoFormat("[REST]: Request Length {0}", _request.ContentLength);
|
||||
m_log.InfoFormat("[REST]: Sending Web Request {0}", buildUri());
|
||||
@@ -384,7 +398,22 @@ namespace OpenSim.Framework.Communications
|
||||
length = src.Read(buf, 0, 1024);
|
||||
}
|
||||
|
||||
_response = (HttpWebResponse) _request.GetResponse();
|
||||
try
|
||||
{
|
||||
_response = (HttpWebResponse)_request.GetResponse();
|
||||
}
|
||||
catch (WebException e)
|
||||
{
|
||||
m_log.WarnFormat("[REST]: Request {0} {1} failed with status {2} and message {3}",
|
||||
RequestMethod, _request.RequestUri, e.Status, e.Message);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.WarnFormat(
|
||||
"[REST]: Request {0} {1} failed with exception {2} {3}",
|
||||
RequestMethod, _request.RequestUri, e.Message, e.StackTrace);
|
||||
}
|
||||
|
||||
|
||||
// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request);
|
||||
|
||||
@@ -423,7 +452,7 @@ namespace OpenSim.Framework.Communications
|
||||
try
|
||||
{
|
||||
// Perform the operation; if sucessful set the result
|
||||
Stream s = Request();
|
||||
Stream s = Request(null);
|
||||
ar.SetAsCompleted(s, false);
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
using OpenSim.Framework.Configuration.XML;
|
||||
|
||||
namespace OpenSim.Framework.Configuration.HTTP
|
||||
{
|
||||
public class HTTPConfiguration : IGenericConfig
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private RemoteConfigSettings remoteConfigSettings;
|
||||
|
||||
private XmlConfiguration xmlConfig;
|
||||
|
||||
private string configFileName = String.Empty;
|
||||
|
||||
public HTTPConfiguration()
|
||||
{
|
||||
remoteConfigSettings = new RemoteConfigSettings("remoteconfig.xml");
|
||||
xmlConfig = new XmlConfiguration();
|
||||
}
|
||||
|
||||
public void SetFileName(string fileName)
|
||||
{
|
||||
configFileName = fileName;
|
||||
}
|
||||
|
||||
public void LoadData()
|
||||
{
|
||||
try
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
byte[] buf = new byte[8192];
|
||||
HttpWebRequest request =
|
||||
(HttpWebRequest) WebRequest.Create(remoteConfigSettings.baseConfigURL + configFileName);
|
||||
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
||||
{
|
||||
using (Stream resStream = response.GetResponseStream())
|
||||
{
|
||||
string tempString = null;
|
||||
int count = 0;
|
||||
|
||||
do
|
||||
{
|
||||
count = resStream.Read(buf, 0, buf.Length);
|
||||
if (count != 0)
|
||||
{
|
||||
tempString = Util.UTF8.GetString(buf, 0, count);
|
||||
sb.Append(tempString);
|
||||
}
|
||||
}
|
||||
while (count > 0);
|
||||
|
||||
LoadDataFromString(sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (WebException)
|
||||
{
|
||||
m_log.Warn("Unable to connect to remote configuration file (" +
|
||||
remoteConfigSettings.baseConfigURL + configFileName +
|
||||
"). Creating local file instead.");
|
||||
xmlConfig.SetFileName(configFileName);
|
||||
xmlConfig.LoadData();
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadDataFromString(string data)
|
||||
{
|
||||
xmlConfig.LoadDataFromString(data);
|
||||
}
|
||||
|
||||
public string GetAttribute(string attributeName)
|
||||
{
|
||||
return xmlConfig.GetAttribute(attributeName);
|
||||
}
|
||||
|
||||
public bool SetAttribute(string attributeName, string attributeValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Commit()
|
||||
{
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("OpenSim.Framework.Configuration.HTTP")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("http://opensimulator.org")]
|
||||
[assembly: AssemblyProduct("OpenSim")]
|
||||
[assembly: AssemblyCopyright("OpenSimulator develoeprs")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("cb78b672-d000-4f93-88f9-dae151cc0061")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.8.0.*")]
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("OpenSim.Framework.Configuration.XML")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("http://opensimulator.org")]
|
||||
[assembly: AssemblyProduct("OpenSim")]
|
||||
[assembly: AssemblyCopyright("OpenSimulator developers")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("eeb880df-0112-4c3d-87ed-b2108d614c55")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.8.0.*")]
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
|
||||
namespace OpenSim.Framework.Configuration.XML
|
||||
{
|
||||
public class XmlConfiguration : IGenericConfig
|
||||
{
|
||||
private XmlDocument doc;
|
||||
private XmlNode rootNode;
|
||||
private XmlNode configNode;
|
||||
private string fileName;
|
||||
private bool createdFile = false;
|
||||
|
||||
public void SetFileName(string file)
|
||||
{
|
||||
fileName = file;
|
||||
}
|
||||
|
||||
private void LoadDataToClass()
|
||||
{
|
||||
rootNode = doc.SelectSingleNode("Root");
|
||||
if (null == rootNode)
|
||||
throw new Exception("Error: Invalid .xml File. Missing <Root>");
|
||||
|
||||
configNode = rootNode.SelectSingleNode("Config");
|
||||
if (null == configNode)
|
||||
throw new Exception("Error: Invalid .xml File. <Root> should contain a <Config>");
|
||||
}
|
||||
|
||||
public void LoadData()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
doc = new XmlDocument();
|
||||
if (File.Exists(fileName))
|
||||
{
|
||||
XmlTextReader reader = new XmlTextReader(fileName);
|
||||
reader.WhitespaceHandling = WhitespaceHandling.None;
|
||||
doc.Load(reader);
|
||||
reader.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
createdFile = true;
|
||||
rootNode = doc.CreateNode(XmlNodeType.Element, "Root", String.Empty);
|
||||
doc.AppendChild(rootNode);
|
||||
configNode = doc.CreateNode(XmlNodeType.Element, "Config", String.Empty);
|
||||
rootNode.AppendChild(configNode);
|
||||
}
|
||||
|
||||
LoadDataToClass();
|
||||
|
||||
if (createdFile)
|
||||
{
|
||||
Commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadDataFromString(string data)
|
||||
{
|
||||
doc = new XmlDocument();
|
||||
doc.LoadXml(data);
|
||||
|
||||
LoadDataToClass();
|
||||
}
|
||||
|
||||
public string GetAttribute(string attributeName)
|
||||
{
|
||||
string result = null;
|
||||
if (configNode.Attributes[attributeName] != null)
|
||||
{
|
||||
result = ((XmlAttribute) configNode.Attributes.GetNamedItem(attributeName)).Value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool SetAttribute(string attributeName, string attributeValue)
|
||||
{
|
||||
if (configNode.Attributes[attributeName] != null)
|
||||
{
|
||||
((XmlAttribute) configNode.Attributes.GetNamedItem(attributeName)).Value = attributeValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
XmlAttribute attri;
|
||||
attri = doc.CreateAttribute(attributeName);
|
||||
attri.Value = attributeValue;
|
||||
configNode.Attributes.Append(attri);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Commit()
|
||||
{
|
||||
if (string.IsNullOrEmpty(fileName))
|
||||
return;
|
||||
|
||||
if (!Directory.Exists(Util.configDir()))
|
||||
{
|
||||
Directory.CreateDirectory(Util.configDir());
|
||||
}
|
||||
doc.Save(fileName);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
configNode = null;
|
||||
rootNode = null;
|
||||
doc = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,530 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
//using OpenSim.Framework.Console;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
public class ConfigurationMember
|
||||
{
|
||||
#region Delegates
|
||||
|
||||
public delegate bool ConfigurationOptionResult(string configuration_key, object configuration_result);
|
||||
|
||||
public delegate void ConfigurationOptionsLoad();
|
||||
|
||||
#endregion
|
||||
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private int cE = 0;
|
||||
|
||||
private string configurationDescription = String.Empty;
|
||||
private string configurationFilename = String.Empty;
|
||||
private XmlNode configurationFromXMLNode = null;
|
||||
private List<ConfigurationOption> configurationOptions = new List<ConfigurationOption>();
|
||||
private IGenericConfig configurationPlugin = null;
|
||||
|
||||
/// <summary>
|
||||
/// This is the default configuration DLL loaded
|
||||
/// </summary>
|
||||
private string configurationPluginFilename = "OpenSim.Framework.Configuration.XML.dll";
|
||||
|
||||
private ConfigurationOptionsLoad loadFunction;
|
||||
private ConfigurationOptionResult resultFunction;
|
||||
|
||||
private bool useConsoleToPromptOnError = true;
|
||||
|
||||
public ConfigurationMember(string configuration_filename, string configuration_description,
|
||||
ConfigurationOptionsLoad load_function, ConfigurationOptionResult result_function, bool use_console_to_prompt_on_error)
|
||||
{
|
||||
configurationFilename = configuration_filename;
|
||||
configurationDescription = configuration_description;
|
||||
loadFunction = load_function;
|
||||
resultFunction = result_function;
|
||||
useConsoleToPromptOnError = use_console_to_prompt_on_error;
|
||||
}
|
||||
|
||||
public ConfigurationMember(XmlNode configuration_xml, string configuration_description,
|
||||
ConfigurationOptionsLoad load_function, ConfigurationOptionResult result_function, bool use_console_to_prompt_on_error)
|
||||
{
|
||||
configurationFilename = String.Empty;
|
||||
configurationFromXMLNode = configuration_xml;
|
||||
configurationDescription = configuration_description;
|
||||
loadFunction = load_function;
|
||||
resultFunction = result_function;
|
||||
useConsoleToPromptOnError = use_console_to_prompt_on_error;
|
||||
}
|
||||
|
||||
public void setConfigurationFilename(string filename)
|
||||
{
|
||||
configurationFilename = filename;
|
||||
}
|
||||
|
||||
public void setConfigurationDescription(string desc)
|
||||
{
|
||||
configurationDescription = desc;
|
||||
}
|
||||
|
||||
public void setConfigurationResultFunction(ConfigurationOptionResult result)
|
||||
{
|
||||
resultFunction = result;
|
||||
}
|
||||
|
||||
public void forceConfigurationPluginLibrary(string dll_filename)
|
||||
{
|
||||
configurationPluginFilename = dll_filename;
|
||||
}
|
||||
|
||||
private void checkAndAddConfigOption(ConfigurationOption option)
|
||||
{
|
||||
if ((option.configurationKey != String.Empty && option.configurationQuestion != String.Empty) ||
|
||||
(option.configurationKey != String.Empty && option.configurationUseDefaultNoPrompt))
|
||||
{
|
||||
if (!configurationOptions.Contains(option))
|
||||
{
|
||||
configurationOptions.Add(option);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Info(
|
||||
"Required fields for adding a configuration option is invalid. Will not add this option (" +
|
||||
option.configurationKey + ")");
|
||||
}
|
||||
}
|
||||
|
||||
public void addConfigurationOption(string configuration_key,
|
||||
ConfigurationOption.ConfigurationTypes configuration_type,
|
||||
string configuration_question, string configuration_default,
|
||||
bool use_default_no_prompt)
|
||||
{
|
||||
ConfigurationOption configOption = new ConfigurationOption();
|
||||
configOption.configurationKey = configuration_key;
|
||||
configOption.configurationQuestion = configuration_question;
|
||||
configOption.configurationDefault = configuration_default;
|
||||
configOption.configurationType = configuration_type;
|
||||
configOption.configurationUseDefaultNoPrompt = use_default_no_prompt;
|
||||
configOption.shouldIBeAsked = null; //Assumes true, I can ask whenever
|
||||
checkAndAddConfigOption(configOption);
|
||||
}
|
||||
|
||||
public void addConfigurationOption(string configuration_key,
|
||||
ConfigurationOption.ConfigurationTypes configuration_type,
|
||||
string configuration_question, string configuration_default,
|
||||
bool use_default_no_prompt,
|
||||
ConfigurationOption.ConfigurationOptionShouldBeAsked shouldIBeAskedDelegate)
|
||||
{
|
||||
ConfigurationOption configOption = new ConfigurationOption();
|
||||
configOption.configurationKey = configuration_key;
|
||||
configOption.configurationQuestion = configuration_question;
|
||||
configOption.configurationDefault = configuration_default;
|
||||
configOption.configurationType = configuration_type;
|
||||
configOption.configurationUseDefaultNoPrompt = use_default_no_prompt;
|
||||
configOption.shouldIBeAsked = shouldIBeAskedDelegate;
|
||||
checkAndAddConfigOption(configOption);
|
||||
}
|
||||
|
||||
// TEMP - REMOVE
|
||||
public void performConfigurationRetrieve()
|
||||
{
|
||||
if (cE > 1)
|
||||
m_log.Error("READING CONFIGURATION COUT: " + cE.ToString());
|
||||
|
||||
|
||||
configurationPlugin = LoadConfigDll(configurationPluginFilename);
|
||||
configurationOptions.Clear();
|
||||
if (loadFunction == null)
|
||||
{
|
||||
m_log.Error("Load Function for '" + configurationDescription +
|
||||
"' is null. Refusing to run configuration.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (resultFunction == null)
|
||||
{
|
||||
m_log.Error("Result Function for '" + configurationDescription +
|
||||
"' is null. Refusing to run configuration.");
|
||||
return;
|
||||
}
|
||||
|
||||
//m_log.Debug("[CONFIG]: Calling Configuration Load Function...");
|
||||
loadFunction();
|
||||
|
||||
if (configurationOptions.Count <= 0)
|
||||
{
|
||||
m_log.Error("[CONFIG]: No configuration options were specified for '" + configurationOptions +
|
||||
"'. Refusing to continue configuration.");
|
||||
return;
|
||||
}
|
||||
|
||||
bool useFile = true;
|
||||
if (configurationPlugin == null)
|
||||
{
|
||||
m_log.Error("[CONFIG]: Configuration Plugin NOT LOADED!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (configurationFilename.Trim() != String.Empty)
|
||||
{
|
||||
configurationPlugin.SetFileName(configurationFilename);
|
||||
try
|
||||
{
|
||||
configurationPlugin.LoadData();
|
||||
useFile = true;
|
||||
}
|
||||
catch (XmlException e)
|
||||
{
|
||||
m_log.WarnFormat("[CONFIG] Not using {0}: {1}",
|
||||
configurationFilename,
|
||||
e.Message.ToString());
|
||||
//m_log.Error("Error loading " + configurationFilename + ": " + e.ToString());
|
||||
useFile = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (configurationFromXMLNode != null)
|
||||
{
|
||||
m_log.Info("Loading from XML Node, will not save to the file");
|
||||
configurationPlugin.LoadDataFromString(configurationFromXMLNode.OuterXml);
|
||||
}
|
||||
|
||||
m_log.Info("XML Configuration Filename is not valid; will not save to the file.");
|
||||
useFile = false;
|
||||
}
|
||||
|
||||
foreach (ConfigurationOption configOption in configurationOptions)
|
||||
{
|
||||
bool convertSuccess = false;
|
||||
object return_result = null;
|
||||
string errorMessage = String.Empty;
|
||||
bool ignoreNextFromConfig = false;
|
||||
while (convertSuccess == false)
|
||||
{
|
||||
string console_result = String.Empty;
|
||||
string attribute = null;
|
||||
if (useFile || configurationFromXMLNode != null)
|
||||
{
|
||||
if (!ignoreNextFromConfig)
|
||||
{
|
||||
attribute = configurationPlugin.GetAttribute(configOption.configurationKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
ignoreNextFromConfig = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (attribute == null)
|
||||
{
|
||||
if (configOption.configurationUseDefaultNoPrompt || useConsoleToPromptOnError == false)
|
||||
{
|
||||
console_result = configOption.configurationDefault;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((configOption.shouldIBeAsked != null &&
|
||||
configOption.shouldIBeAsked(configOption.configurationKey)) ||
|
||||
configOption.shouldIBeAsked == null)
|
||||
{
|
||||
if (configurationDescription.Trim() != String.Empty)
|
||||
{
|
||||
console_result =
|
||||
MainConsole.Instance.CmdPrompt(
|
||||
configurationDescription + ": " + configOption.configurationQuestion,
|
||||
configOption.configurationDefault);
|
||||
}
|
||||
else
|
||||
{
|
||||
console_result =
|
||||
MainConsole.Instance.CmdPrompt(configOption.configurationQuestion,
|
||||
configOption.configurationDefault);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Dont Ask! Just use default
|
||||
console_result = configOption.configurationDefault;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
console_result = attribute;
|
||||
}
|
||||
|
||||
// if the first character is a "$", assume it's the name
|
||||
// of an environment variable and substitute with the value of that variable
|
||||
if (console_result.StartsWith("$"))
|
||||
console_result = Environment.GetEnvironmentVariable(console_result.Substring(1));
|
||||
|
||||
switch (configOption.configurationType)
|
||||
{
|
||||
case ConfigurationOption.ConfigurationTypes.TYPE_STRING:
|
||||
return_result = console_result;
|
||||
convertSuccess = true;
|
||||
break;
|
||||
case ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY:
|
||||
if (console_result.Length > 0)
|
||||
{
|
||||
return_result = console_result;
|
||||
convertSuccess = true;
|
||||
}
|
||||
errorMessage = "a string that is not empty";
|
||||
break;
|
||||
case ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN:
|
||||
bool boolResult;
|
||||
if (Boolean.TryParse(console_result, out boolResult))
|
||||
{
|
||||
convertSuccess = true;
|
||||
return_result = boolResult;
|
||||
}
|
||||
errorMessage = "'true' or 'false' (Boolean)";
|
||||
break;
|
||||
case ConfigurationOption.ConfigurationTypes.TYPE_BYTE:
|
||||
byte byteResult;
|
||||
if (Byte.TryParse(console_result, out byteResult))
|
||||
{
|
||||
convertSuccess = true;
|
||||
return_result = byteResult;
|
||||
}
|
||||
errorMessage = "a byte (Byte)";
|
||||
break;
|
||||
case ConfigurationOption.ConfigurationTypes.TYPE_CHARACTER:
|
||||
char charResult;
|
||||
if (Char.TryParse(console_result, out charResult))
|
||||
{
|
||||
convertSuccess = true;
|
||||
return_result = charResult;
|
||||
}
|
||||
errorMessage = "a character (Char)";
|
||||
break;
|
||||
case ConfigurationOption.ConfigurationTypes.TYPE_INT16:
|
||||
short shortResult;
|
||||
if (Int16.TryParse(console_result, out shortResult))
|
||||
{
|
||||
convertSuccess = true;
|
||||
return_result = shortResult;
|
||||
}
|
||||
errorMessage = "a signed 32 bit integer (short)";
|
||||
break;
|
||||
case ConfigurationOption.ConfigurationTypes.TYPE_INT32:
|
||||
int intResult;
|
||||
if (Int32.TryParse(console_result, out intResult))
|
||||
{
|
||||
convertSuccess = true;
|
||||
return_result = intResult;
|
||||
}
|
||||
errorMessage = "a signed 32 bit integer (int)";
|
||||
break;
|
||||
case ConfigurationOption.ConfigurationTypes.TYPE_INT64:
|
||||
long longResult;
|
||||
if (Int64.TryParse(console_result, out longResult))
|
||||
{
|
||||
convertSuccess = true;
|
||||
return_result = longResult;
|
||||
}
|
||||
errorMessage = "a signed 32 bit integer (long)";
|
||||
break;
|
||||
case ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS:
|
||||
IPAddress ipAddressResult;
|
||||
if (IPAddress.TryParse(console_result, out ipAddressResult))
|
||||
{
|
||||
convertSuccess = true;
|
||||
return_result = ipAddressResult;
|
||||
}
|
||||
errorMessage = "an IP Address (IPAddress)";
|
||||
break;
|
||||
case ConfigurationOption.ConfigurationTypes.TYPE_UUID:
|
||||
UUID uuidResult;
|
||||
if (UUID.TryParse(console_result, out uuidResult))
|
||||
{
|
||||
convertSuccess = true;
|
||||
return_result = uuidResult;
|
||||
}
|
||||
errorMessage = "a UUID (UUID)";
|
||||
break;
|
||||
case ConfigurationOption.ConfigurationTypes.TYPE_UUID_NULL_FREE:
|
||||
UUID uuidResult2;
|
||||
if (UUID.TryParse(console_result, out uuidResult2))
|
||||
{
|
||||
convertSuccess = true;
|
||||
|
||||
if (uuidResult2 == UUID.Zero)
|
||||
uuidResult2 = UUID.Random();
|
||||
|
||||
return_result = uuidResult2;
|
||||
}
|
||||
errorMessage = "a non-null UUID (UUID)";
|
||||
break;
|
||||
case ConfigurationOption.ConfigurationTypes.TYPE_Vector3:
|
||||
Vector3 vectorResult;
|
||||
if (Vector3.TryParse(console_result, out vectorResult))
|
||||
{
|
||||
convertSuccess = true;
|
||||
return_result = vectorResult;
|
||||
}
|
||||
errorMessage = "a vector (Vector3)";
|
||||
break;
|
||||
case ConfigurationOption.ConfigurationTypes.TYPE_UINT16:
|
||||
ushort ushortResult;
|
||||
if (UInt16.TryParse(console_result, out ushortResult))
|
||||
{
|
||||
convertSuccess = true;
|
||||
return_result = ushortResult;
|
||||
}
|
||||
errorMessage = "an unsigned 16 bit integer (ushort)";
|
||||
break;
|
||||
case ConfigurationOption.ConfigurationTypes.TYPE_UINT32:
|
||||
uint uintResult;
|
||||
if (UInt32.TryParse(console_result, out uintResult))
|
||||
{
|
||||
convertSuccess = true;
|
||||
return_result = uintResult;
|
||||
}
|
||||
errorMessage = "an unsigned 32 bit integer (uint)";
|
||||
break;
|
||||
case ConfigurationOption.ConfigurationTypes.TYPE_UINT64:
|
||||
ulong ulongResult;
|
||||
if (UInt64.TryParse(console_result, out ulongResult))
|
||||
{
|
||||
convertSuccess = true;
|
||||
return_result = ulongResult;
|
||||
}
|
||||
errorMessage = "an unsigned 64 bit integer (ulong)";
|
||||
break;
|
||||
case ConfigurationOption.ConfigurationTypes.TYPE_FLOAT:
|
||||
float floatResult;
|
||||
if (
|
||||
float.TryParse(console_result, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, Culture.NumberFormatInfo,
|
||||
out floatResult))
|
||||
{
|
||||
convertSuccess = true;
|
||||
return_result = floatResult;
|
||||
}
|
||||
errorMessage = "a single-precision floating point number (float)";
|
||||
break;
|
||||
case ConfigurationOption.ConfigurationTypes.TYPE_DOUBLE:
|
||||
double doubleResult;
|
||||
if (
|
||||
Double.TryParse(console_result, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, Culture.NumberFormatInfo,
|
||||
out doubleResult))
|
||||
{
|
||||
convertSuccess = true;
|
||||
return_result = doubleResult;
|
||||
}
|
||||
errorMessage = "an double-precision floating point number (double)";
|
||||
break;
|
||||
}
|
||||
|
||||
if (convertSuccess)
|
||||
{
|
||||
if (useFile)
|
||||
{
|
||||
configurationPlugin.SetAttribute(configOption.configurationKey, console_result);
|
||||
}
|
||||
|
||||
if (!resultFunction(configOption.configurationKey, return_result))
|
||||
{
|
||||
m_log.Info(
|
||||
"The handler for the last configuration option denied that input, please try again.");
|
||||
convertSuccess = false;
|
||||
ignoreNextFromConfig = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (configOption.configurationUseDefaultNoPrompt)
|
||||
{
|
||||
m_log.Error(string.Format(
|
||||
"[CONFIG]: [{3}]:[{1}] is not valid default for parameter [{0}].\nThe configuration result must be parsable to {2}.\n",
|
||||
configOption.configurationKey, console_result, errorMessage,
|
||||
configurationFilename));
|
||||
convertSuccess = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Warn(string.Format(
|
||||
"[CONFIG]: [{3}]:[{1}] is not a valid value [{0}].\nThe configuration result must be parsable to {2}.\n",
|
||||
configOption.configurationKey, console_result, errorMessage,
|
||||
configurationFilename));
|
||||
ignoreNextFromConfig = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useFile)
|
||||
{
|
||||
configurationPlugin.Commit();
|
||||
configurationPlugin.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private static IGenericConfig LoadConfigDll(string dllName)
|
||||
{
|
||||
Assembly pluginAssembly = Assembly.LoadFrom(dllName);
|
||||
IGenericConfig plug = null;
|
||||
|
||||
foreach (Type pluginType in pluginAssembly.GetTypes())
|
||||
{
|
||||
if (pluginType.IsPublic)
|
||||
{
|
||||
if (!pluginType.IsAbstract)
|
||||
{
|
||||
Type typeInterface = pluginType.GetInterface("IGenericConfig", true);
|
||||
|
||||
if (typeInterface != null)
|
||||
{
|
||||
plug =
|
||||
(IGenericConfig) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pluginAssembly = null;
|
||||
return plug;
|
||||
}
|
||||
|
||||
public void forceSetConfigurationOption(string configuration_key, string configuration_value)
|
||||
{
|
||||
configurationPlugin.LoadData();
|
||||
configurationPlugin.SetAttribute(configuration_key, configuration_value);
|
||||
configurationPlugin.Commit();
|
||||
configurationPlugin.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
-29
@@ -27,37 +27,22 @@
|
||||
|
||||
using System;
|
||||
|
||||
namespace OpenSim.Framework.Configuration.HTTP
|
||||
namespace OpenSim.Framework.Console
|
||||
{
|
||||
public class RemoteConfigSettings
|
||||
/// <summary>
|
||||
/// This will be a set of typical column sizes to allow greater consistency between console commands.
|
||||
/// </summary>
|
||||
public static class ConsoleDisplayUtil
|
||||
{
|
||||
private ConfigurationMember configMember;
|
||||
public const int CoordTupleSize = 11;
|
||||
public const int PortSize = 5;
|
||||
|
||||
public string baseConfigURL = String.Empty;
|
||||
public const int EstateNameSize = 20;
|
||||
public const int ParcelNameSize = 40;
|
||||
public const int RegionNameSize = 20;
|
||||
public const int UserNameSize = 35;
|
||||
|
||||
public RemoteConfigSettings(string filename)
|
||||
{
|
||||
configMember =
|
||||
new ConfigurationMember(filename, "REMOTE CONFIG SETTINGS", loadConfigurationOptions,
|
||||
handleIncomingConfiguration,true);
|
||||
configMember.forceConfigurationPluginLibrary("OpenSim.Framework.Configuration.XML.dll");
|
||||
configMember.performConfigurationRetrieve();
|
||||
}
|
||||
|
||||
public void loadConfigurationOptions()
|
||||
{
|
||||
configMember.addConfigurationOption("base_config_url",
|
||||
ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
|
||||
"URL Containing Configuration Files", "http://localhost/", false);
|
||||
}
|
||||
|
||||
public bool handleIncomingConfiguration(string configuration_key, object configuration_result)
|
||||
{
|
||||
if (configuration_key == "base_config_url")
|
||||
{
|
||||
baseConfigURL = (string) configuration_result;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public const int UuidSize = 36;
|
||||
public const int VectorSize = 15;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -252,24 +252,82 @@ namespace OpenSim.Framework.Console
|
||||
/// The strings "~" and "-~" are valid in components. The first substitutes float.MaxValue whilst the second is float.MinValue
|
||||
/// Other than that, component values must be numeric.
|
||||
/// </param>
|
||||
/// <param name='blankComponentFunc'></param>
|
||||
/// <param name='blankComponentFunc'>
|
||||
/// Behaviour if component is blank. If null then conversion fails on a blank component.
|
||||
/// </param>
|
||||
/// <param name='vector'></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryParseConsoleVector(
|
||||
string rawConsoleVector, Func<string, string> blankComponentFunc, out Vector3 vector)
|
||||
{
|
||||
List<string> components = rawConsoleVector.Split(VectorSeparatorChars).ToList();
|
||||
|
||||
if (components.Count < 1 || components.Count > 3)
|
||||
return Vector3.TryParse(CookVector(rawConsoleVector, 3, blankComponentFunc), out vector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a vector input from the console to an OpenMetaverse.Vector2
|
||||
/// </summary>
|
||||
/// <param name='rawConsoleVector'>
|
||||
/// A string in the form <x>,<y> where there is no space between values.
|
||||
/// Any component can be missing (e.g. ,40). blankComponentFunc is invoked to replace the blank with a suitable value
|
||||
/// Also, if the blank component is at the end, then the comma can be missed off entirely (e.g. 40)
|
||||
/// The strings "~" and "-~" are valid in components. The first substitutes float.MaxValue whilst the second is float.MinValue
|
||||
/// Other than that, component values must be numeric.
|
||||
/// </param>
|
||||
/// <param name='blankComponentFunc'>
|
||||
/// Behaviour if component is blank. If null then conversion fails on a blank component.
|
||||
/// </param>
|
||||
/// <param name='vector'></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryParseConsole2DVector(
|
||||
string rawConsoleVector, Func<string, string> blankComponentFunc, out Vector2 vector)
|
||||
{
|
||||
// We don't use Vector2.TryParse() for now because for some reason it expects an input with 3 components
|
||||
// rather than 2.
|
||||
string cookedVector = CookVector(rawConsoleVector, 2, blankComponentFunc);
|
||||
|
||||
if (cookedVector == null)
|
||||
{
|
||||
vector = Vector3.Zero;
|
||||
vector = Vector2.Zero;
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] cookedComponents = cookedVector.Split(VectorSeparatorChars);
|
||||
|
||||
vector = new Vector2(float.Parse(cookedComponents[0]), float.Parse(cookedComponents[1]));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//return Vector2.TryParse(CookVector(rawConsoleVector, 2, blankComponentFunc), out vector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a raw console vector into a vector that can be be parsed by the relevant OpenMetaverse.TryParse()
|
||||
/// </summary>
|
||||
/// <param name='rawConsoleVector'></param>
|
||||
/// <param name='dimensions'></param>
|
||||
/// <param name='blankComponentFunc'></param>
|
||||
/// <returns>null if conversion was not possible</returns>
|
||||
private static string CookVector(
|
||||
string rawConsoleVector, int dimensions, Func<string, string> blankComponentFunc)
|
||||
{
|
||||
List<string> components = rawConsoleVector.Split(VectorSeparatorChars).ToList();
|
||||
|
||||
for (int i = components.Count; i < 3; i++)
|
||||
components.Add("");
|
||||
if (components.Count < 1 || components.Count > dimensions)
|
||||
return null;
|
||||
|
||||
List<string> semiDigestedComponents
|
||||
if (components.Count < dimensions)
|
||||
{
|
||||
if (blankComponentFunc == null)
|
||||
return null;
|
||||
else
|
||||
for (int i = components.Count; i < dimensions; i++)
|
||||
components.Add("");
|
||||
}
|
||||
|
||||
List<string> cookedComponents
|
||||
= components.ConvertAll<string>(
|
||||
c =>
|
||||
{
|
||||
@@ -283,11 +341,7 @@ namespace OpenSim.Framework.Console
|
||||
return c;
|
||||
});
|
||||
|
||||
string semiDigestedConsoleVector = string.Join(VectorSeparator, semiDigestedComponents.ToArray());
|
||||
|
||||
// m_log.DebugFormat("[CONSOLE UTIL]: Parsing {0} into OpenMetaverse.Vector3", semiDigestedConsoleVector);
|
||||
|
||||
return Vector3.TryParse(semiDigestedConsoleVector, out vector);
|
||||
return string.Join(VectorSeparator, cookedComponents.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,11 @@ namespace OpenSim.Framework.Console
|
||||
// private readonly object m_syncRoot = new object();
|
||||
private const string LOGLEVEL_NONE = "(none)";
|
||||
|
||||
// Used to extract categories for colourization.
|
||||
private Regex m_categoryRegex
|
||||
= new Regex(
|
||||
@"^(?<Front>.*?)\[(?<Category>[^\]]+)\]:?(?<End>.*)", RegexOptions.Singleline | RegexOptions.Compiled);
|
||||
|
||||
private int m_cursorYPosition = -1;
|
||||
private int m_cursorXPosition = 0;
|
||||
private StringBuilder m_commandLine = new StringBuilder();
|
||||
@@ -280,11 +285,8 @@ namespace OpenSim.Framework.Console
|
||||
string outText = text;
|
||||
|
||||
if (level != LOGLEVEL_NONE)
|
||||
{
|
||||
string regex = @"^(?<Front>.*?)\[(?<Category>[^\]]+)\]:?(?<End>.*)";
|
||||
|
||||
Regex RE = new Regex(regex, RegexOptions.Multiline);
|
||||
MatchCollection matches = RE.Matches(text);
|
||||
{
|
||||
MatchCollection matches = m_categoryRegex.Matches(text);
|
||||
|
||||
if (matches.Count == 1)
|
||||
{
|
||||
|
||||
@@ -40,7 +40,9 @@ namespace OpenSim.Framework.Console
|
||||
/// </summary>
|
||||
public class MockConsole : ICommandConsole
|
||||
{
|
||||
#pragma warning disable 0067
|
||||
public event OnOutputDelegate OnOutput;
|
||||
#pragma warning restore 0067
|
||||
|
||||
private MockCommands m_commands = new MockCommands();
|
||||
|
||||
|
||||
@@ -25,6 +25,10 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
@@ -111,5 +115,50 @@ namespace OpenSim.Framework
|
||||
}
|
||||
}
|
||||
|
||||
public EstateBan() { }
|
||||
|
||||
public Dictionary<string, object> ToMap()
|
||||
{
|
||||
Dictionary<string, object> map = new Dictionary<string, object>();
|
||||
PropertyInfo[] properties = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||
foreach (PropertyInfo p in properties)
|
||||
map[p.Name] = p.GetValue(this, null);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
public EstateBan(Dictionary<string, object> map)
|
||||
{
|
||||
foreach (KeyValuePair<string, object> kvp in map)
|
||||
{
|
||||
PropertyInfo p = this.GetType().GetProperty(kvp.Key, BindingFlags.Public | BindingFlags.Instance);
|
||||
if (p == null)
|
||||
continue;
|
||||
object value = p.GetValue(this, null);
|
||||
if (value is String)
|
||||
p.SetValue(this, map[p.Name], null);
|
||||
else if (value is UInt32)
|
||||
p.SetValue(this, UInt32.Parse((string)map[p.Name]), null);
|
||||
else if (value is Boolean)
|
||||
p.SetValue(this, Boolean.Parse((string)map[p.Name]), null);
|
||||
else if (value is UUID)
|
||||
p.SetValue(this, UUID.Parse((string)map[p.Name]), null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// For debugging
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
Dictionary<string, object> map = ToMap();
|
||||
string result = string.Empty;
|
||||
foreach (KeyValuePair<string, object> kvp in map)
|
||||
result += string.Format("{0}: {1} {2}", kvp.Key, kvp.Value, Environment.NewLine);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
@@ -411,5 +412,119 @@ namespace OpenSim.Framework
|
||||
{
|
||||
return l_EstateGroups.Contains(groupID);
|
||||
}
|
||||
|
||||
public Dictionary<string, object> ToMap()
|
||||
{
|
||||
Dictionary<string, object> map = new Dictionary<string, object>();
|
||||
PropertyInfo[] properties = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||
foreach (PropertyInfo p in properties)
|
||||
{
|
||||
// EstateBans is a complex type, let's treat it as special
|
||||
if (p.Name == "EstateBans")
|
||||
continue;
|
||||
|
||||
object value = p.GetValue(this, null);
|
||||
if (value != null)
|
||||
{
|
||||
if (p.PropertyType.IsArray) // of UUIDs
|
||||
{
|
||||
if (((Array)value).Length > 0)
|
||||
{
|
||||
string[] args = new string[((Array)value).Length];
|
||||
int index = 0;
|
||||
foreach (object o in (Array)value)
|
||||
args[index++] = o.ToString();
|
||||
map[p.Name] = String.Join(",", args);
|
||||
}
|
||||
}
|
||||
else // simple types
|
||||
map[p.Name] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// EstateBans are special
|
||||
if (EstateBans.Length > 0)
|
||||
{
|
||||
Dictionary<string, object> bans = new Dictionary<string, object>();
|
||||
int i = 0;
|
||||
foreach (EstateBan ban in EstateBans)
|
||||
bans["ban" + i++] = ban.ToMap();
|
||||
map["EstateBans"] = bans;
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For debugging
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
Dictionary<string, object> map = ToMap();
|
||||
String result = String.Empty;
|
||||
|
||||
foreach (KeyValuePair<string, object> kvp in map)
|
||||
{
|
||||
if (kvp.Key == "EstateBans")
|
||||
{
|
||||
result += "EstateBans:" + Environment.NewLine;
|
||||
foreach (KeyValuePair<string, object> ban in (Dictionary<string, object>)kvp.Value)
|
||||
result += ban.Value.ToString();
|
||||
}
|
||||
else
|
||||
result += string.Format("{0}: {1} {2}", kvp.Key, kvp.Value.ToString(), Environment.NewLine);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public EstateSettings(Dictionary<string, object> map)
|
||||
{
|
||||
foreach (KeyValuePair<string, object> kvp in map)
|
||||
{
|
||||
PropertyInfo p = this.GetType().GetProperty(kvp.Key, BindingFlags.Public | BindingFlags.Instance);
|
||||
if (p == null)
|
||||
continue;
|
||||
|
||||
// EstateBans is a complex type, let's treat it as special
|
||||
if (p.Name == "EstateBans")
|
||||
continue;
|
||||
|
||||
if (p.PropertyType.IsArray)
|
||||
{
|
||||
string[] elements = ((string)map[p.Name]).Split(new char[] { ',' });
|
||||
UUID[] uuids = new UUID[elements.Length];
|
||||
int i = 0;
|
||||
foreach (string e in elements)
|
||||
uuids[i++] = new UUID(e);
|
||||
p.SetValue(this, uuids, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
object value = p.GetValue(this, null);
|
||||
if (value is String)
|
||||
p.SetValue(this, map[p.Name], null);
|
||||
else if (value is UInt32)
|
||||
p.SetValue(this, UInt32.Parse((string)map[p.Name]), null);
|
||||
else if (value is Boolean)
|
||||
p.SetValue(this, Boolean.Parse((string)map[p.Name]), null);
|
||||
else if (value is UUID)
|
||||
p.SetValue(this, UUID.Parse((string)map[p.Name]), null);
|
||||
}
|
||||
}
|
||||
|
||||
// EstateBans are special
|
||||
if (map.ContainsKey("EstateBans"))
|
||||
{
|
||||
var banData = ((Dictionary<string, object>)map["EstateBans"]).Values;
|
||||
EstateBan[] bans = new EstateBan[banData.Count];
|
||||
int b = 0;
|
||||
foreach (Dictionary<string, object> ban in banData)
|
||||
bans[b++] = new EstateBan(ban);
|
||||
PropertyInfo bansProperty = this.GetType().GetProperty("EstateBans", BindingFlags.Public | BindingFlags.Instance);
|
||||
bansProperty.SetValue(this, bans, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ namespace OpenSim.Framework
|
||||
int GetParcelMaxPrimCount();
|
||||
int GetSimulatorMaxPrimCount();
|
||||
int GetPrimsFree();
|
||||
Dictionary<UUID, int> GetLandObjectOwners();
|
||||
|
||||
LandData LandData { get; set; }
|
||||
bool[,] LandBitmap { get; set; }
|
||||
|
||||
@@ -35,6 +35,10 @@ namespace OpenSim.Framework
|
||||
/// </summary>
|
||||
public class InventoryItemBase : InventoryNodeBase, ICloneable
|
||||
{
|
||||
public static readonly string SUITCASE_FOLDER_NAME = "My Suitcase";
|
||||
public static readonly sbyte SUITCASE_FOLDER_TYPE = 100;
|
||||
public static readonly sbyte SUITCASE_FOLDER_FAKE_TYPE = 8;
|
||||
|
||||
/// <value>
|
||||
/// The inventory type of the item. This is slightly different from the asset type in some situations.
|
||||
/// </value>
|
||||
@@ -82,12 +86,15 @@ namespace OpenSim.Framework
|
||||
set
|
||||
{
|
||||
m_creatorId = value;
|
||||
|
||||
if ((m_creatorId == null) || !UUID.TryParse(m_creatorId, out m_creatorIdAsUuid))
|
||||
m_creatorIdAsUuid = UUID.Zero;
|
||||
}
|
||||
}
|
||||
protected string m_creatorId;
|
||||
|
||||
/// <value>
|
||||
/// The CreatorId expressed as a UUID.tely
|
||||
/// The CreatorId expressed as a UUID.
|
||||
/// </value>
|
||||
public UUID CreatorIdAsUuid
|
||||
{
|
||||
|
||||
@@ -26,7 +26,10 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Timers;
|
||||
using log4net;
|
||||
|
||||
@@ -45,13 +48,22 @@ namespace OpenSim.Framework.Monitoring
|
||||
public static void RegisterConsoleCommands(ICommandConsole console)
|
||||
{
|
||||
console.Commands.AddCommand(
|
||||
"Debug",
|
||||
"General",
|
||||
false,
|
||||
"debug stats record",
|
||||
"debug stats record start|stop",
|
||||
"stats record",
|
||||
"stats record start|stop",
|
||||
"Control whether stats are being regularly recorded to a separate file.",
|
||||
"For debug purposes. Experimental.",
|
||||
HandleStatsRecordCommand);
|
||||
|
||||
console.Commands.AddCommand(
|
||||
"General",
|
||||
false,
|
||||
"stats save",
|
||||
"stats save <path>",
|
||||
"Save stats snapshot to a file. If the file already exists, then the report is appended.",
|
||||
"For debug purposes. Experimental.",
|
||||
HandleStatsSaveCommand);
|
||||
}
|
||||
|
||||
public static void HandleStatsRecordCommand(string module, string[] cmd)
|
||||
@@ -76,6 +88,27 @@ namespace OpenSim.Framework.Monitoring
|
||||
}
|
||||
}
|
||||
|
||||
public static void HandleStatsSaveCommand(string module, string[] cmd)
|
||||
{
|
||||
ICommandConsole con = MainConsole.Instance;
|
||||
|
||||
if (cmd.Length != 3)
|
||||
{
|
||||
con.Output("Usage: stats save <path>");
|
||||
return;
|
||||
}
|
||||
|
||||
string path = cmd[2];
|
||||
|
||||
using (StreamWriter sw = new StreamWriter(path, true))
|
||||
{
|
||||
foreach (string line in GetReport())
|
||||
sw.WriteLine(line);
|
||||
}
|
||||
|
||||
MainConsole.Instance.OutputFormat("Stats saved to file {0}", path);
|
||||
}
|
||||
|
||||
public static void Start()
|
||||
{
|
||||
if (m_loggingTimer != null)
|
||||
@@ -97,12 +130,22 @@ namespace OpenSim.Framework.Monitoring
|
||||
|
||||
private static void Log(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
m_statsLog.InfoFormat("*** STATS REPORT AT {0} ***", DateTime.Now);
|
||||
|
||||
foreach (string report in StatsManager.GetAllStatsReports())
|
||||
m_statsLog.Info(report);
|
||||
foreach (string line in GetReport())
|
||||
m_statsLog.Info(line);
|
||||
|
||||
m_loggingTimer.Start();
|
||||
}
|
||||
|
||||
private static List<string> GetReport()
|
||||
{
|
||||
List<string> lines = new List<string>();
|
||||
|
||||
lines.Add(string.Format("*** STATS REPORT AT {0} ***", DateTime.Now));
|
||||
|
||||
foreach (string report in StatsManager.GetAllStatsReports())
|
||||
lines.Add(report);
|
||||
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,8 +72,8 @@ namespace OpenSim.Framework.Monitoring
|
||||
console.Commands.AddCommand(
|
||||
"General",
|
||||
false,
|
||||
"show stats",
|
||||
"show stats [list|all|(<category>[.<container>])+",
|
||||
"stats show",
|
||||
"stats show [list|all|(<category>[.<container>])+",
|
||||
"Show statistical information for this server",
|
||||
"If no final argument is specified then legacy statistics information is currently shown.\n"
|
||||
+ "'list' argument will show statistic categories.\n"
|
||||
@@ -84,6 +84,14 @@ namespace OpenSim.Framework.Monitoring
|
||||
+ "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS",
|
||||
HandleShowStatsCommand);
|
||||
|
||||
console.Commands.AddCommand(
|
||||
"General",
|
||||
false,
|
||||
"show stats",
|
||||
"show stats [list|all|(<category>[.<container>])+",
|
||||
"Alias for 'stats show' command",
|
||||
HandleShowStatsCommand);
|
||||
|
||||
StatsLogger.RegisterConsoleCommands(console);
|
||||
}
|
||||
|
||||
@@ -99,6 +107,7 @@ namespace OpenSim.Framework.Monitoring
|
||||
|
||||
string categoryName = components[0];
|
||||
string containerName = components.Length > 1 ? components[1] : null;
|
||||
string statName = components.Length > 2 ? components[2] : null;
|
||||
|
||||
if (categoryName == AllSubCommand)
|
||||
{
|
||||
@@ -128,7 +137,23 @@ namespace OpenSim.Framework.Monitoring
|
||||
SortedDictionary<string, Stat> container;
|
||||
if (category.TryGetValue(containerName, out container))
|
||||
{
|
||||
OutputContainerStatsToConsole(con, container);
|
||||
if (String.IsNullOrEmpty(statName))
|
||||
{
|
||||
OutputContainerStatsToConsole(con, container);
|
||||
}
|
||||
else
|
||||
{
|
||||
Stat stat;
|
||||
if (container.TryGetValue(statName, out stat))
|
||||
{
|
||||
OutputStatToConsole(con, stat);
|
||||
}
|
||||
else
|
||||
{
|
||||
con.OutputFormat(
|
||||
"No such stat {0} in {1}.{2}", statName, categoryName, containerName);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -200,6 +225,11 @@ namespace OpenSim.Framework.Monitoring
|
||||
con.Output(report);
|
||||
}
|
||||
|
||||
private static void OutputStatToConsole(ICommandConsole con, Stat stat)
|
||||
{
|
||||
con.Output(stat.ToConsoleString());
|
||||
}
|
||||
|
||||
// Creates an OSDMap of the format:
|
||||
// { categoryName: {
|
||||
// containerName: {
|
||||
|
||||
@@ -82,12 +82,32 @@ namespace OpenSim.Framework.Monitoring
|
||||
/// </summary>
|
||||
public Func<string> AlarmMethod { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Stat structure associated with this thread.
|
||||
/// </summary>
|
||||
public Stat Stat { get; set; }
|
||||
|
||||
public ThreadWatchdogInfo(Thread thread, int timeout)
|
||||
{
|
||||
Thread = thread;
|
||||
Timeout = timeout;
|
||||
FirstTick = Environment.TickCount & Int32.MaxValue;
|
||||
LastTick = FirstTick;
|
||||
|
||||
Stat
|
||||
= new Stat(
|
||||
thread.Name,
|
||||
string.Format("Last update of thread {0}", thread.Name),
|
||||
"",
|
||||
"ms",
|
||||
"server",
|
||||
"thread",
|
||||
StatType.Pull,
|
||||
MeasuresOfInterest.None,
|
||||
stat => stat.Value = Environment.TickCount & Int32.MaxValue - LastTick,
|
||||
StatVerbosity.Debug);
|
||||
|
||||
StatsManager.RegisterStat(Stat);
|
||||
}
|
||||
|
||||
public ThreadWatchdogInfo(ThreadWatchdogInfo previousTwi)
|
||||
@@ -100,6 +120,11 @@ namespace OpenSim.Framework.Monitoring
|
||||
AlarmIfTimeout = previousTwi.AlarmIfTimeout;
|
||||
AlarmMethod = previousTwi.AlarmMethod;
|
||||
}
|
||||
|
||||
public void Cleanup()
|
||||
{
|
||||
StatsManager.DeregisterStat(Stat);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -238,6 +263,7 @@ namespace OpenSim.Framework.Monitoring
|
||||
m_log.DebugFormat(
|
||||
"[WATCHDOG]: Removing thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId);
|
||||
|
||||
twi.Cleanup();
|
||||
m_threads.Remove(threadID);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -215,7 +215,7 @@ namespace OpenSim.Framework
|
||||
AddinManager.AddinLoadError += on_addinloaderror_;
|
||||
AddinManager.AddinLoaded += on_addinloaded_;
|
||||
|
||||
clear_registry_();
|
||||
clear_registry_(dir);
|
||||
|
||||
suppress_console_output_(true);
|
||||
AddinManager.Initialize(dir);
|
||||
@@ -239,18 +239,19 @@ namespace OpenSim.Framework
|
||||
+ args.Exception.StackTrace);
|
||||
}
|
||||
|
||||
private void clear_registry_()
|
||||
private void clear_registry_(string dir)
|
||||
{
|
||||
// The Mono addin manager (in Mono.Addins.dll version 0.2.0.0)
|
||||
// occasionally seems to corrupt its addin cache
|
||||
// Hence, as a temporary solution we'll remove it before each startup
|
||||
|
||||
try
|
||||
{
|
||||
if (Directory.Exists("addin-db-000"))
|
||||
Directory.Delete("addin-db-000", true);
|
||||
if (Directory.Exists(dir + "/addin-db-000"))
|
||||
Directory.Delete(dir + "/addin-db-000", true);
|
||||
|
||||
if (Directory.Exists("addin-db-001"))
|
||||
Directory.Delete("addin-db-001", true);
|
||||
if (Directory.Exists(dir + "/addin-db-001"))
|
||||
Directory.Delete(dir + "/addin-db-001", true);
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
|
||||
+53
-252
@@ -102,7 +102,6 @@ namespace OpenSim.Framework
|
||||
private static readonly string LogHeader = "[REGION INFO]";
|
||||
|
||||
public bool commFailTF = false;
|
||||
public ConfigurationMember configMember;
|
||||
public string RegionFile = String.Empty;
|
||||
public bool isSandbox = false;
|
||||
public bool Persistent = true;
|
||||
@@ -127,6 +126,7 @@ namespace OpenSim.Framework
|
||||
private int m_physPrimMax = 0;
|
||||
private bool m_clampPrimSize = false;
|
||||
private int m_objectCapacity = 0;
|
||||
private int m_maxPrimsPerUser = -1;
|
||||
private int m_linksetCapacity = 0;
|
||||
private int m_agentCapacity = 0;
|
||||
private string m_regionType = String.Empty;
|
||||
@@ -147,11 +147,32 @@ namespace OpenSim.Framework
|
||||
public uint WorldLocX = 0;
|
||||
public uint WorldLocY = 0;
|
||||
public uint WorldLocZ = 0;
|
||||
|
||||
/// <summary>
|
||||
/// X dimension of the region.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If this is a varregion then the default size set here will be replaced when we load the region config.
|
||||
/// </remarks>
|
||||
public uint RegionSizeX = Constants.RegionSize;
|
||||
|
||||
/// <summary>
|
||||
/// X dimension of the region.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If this is a varregion then the default size set here will be replaced when we load the region config.
|
||||
/// </remarks>
|
||||
public uint RegionSizeY = Constants.RegionSize;
|
||||
|
||||
/// <summary>
|
||||
/// Z dimension of the region.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// XXX: Unknown if this accounts for regions with negative Z.
|
||||
/// </remarks>
|
||||
public uint RegionSizeZ = Constants.RegionHeight;
|
||||
|
||||
private Dictionary<String, String> m_otherSettings = new Dictionary<string, string>();
|
||||
private Dictionary<String, String> m_extraSettings = new Dictionary<string, string>();
|
||||
|
||||
// Apparently, we're applying the same estatesettings regardless of whether it's local or remote.
|
||||
|
||||
@@ -203,7 +224,6 @@ namespace OpenSim.Framework
|
||||
try
|
||||
{
|
||||
// This will throw if it's not legal Nini XML format
|
||||
// and thereby toss it to the legacy loader
|
||||
//
|
||||
IConfigSource xmlsource = new XmlConfigSource(filename);
|
||||
|
||||
@@ -216,21 +236,18 @@ namespace OpenSim.Framework
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
configMember =
|
||||
new ConfigurationMember(filename, description, loadConfigurationOptions, handleIncomingConfiguration, !skipConsoleConfig);
|
||||
configMember.performConfigurationRetrieve();
|
||||
RegionFile = filename;
|
||||
}
|
||||
|
||||
// The web loader uses this
|
||||
//
|
||||
public RegionInfo(string description, XmlNode xmlNode, bool skipConsoleConfig, IConfigSource configSource)
|
||||
{
|
||||
// m_configSource = configSource;
|
||||
configMember =
|
||||
new ConfigurationMember(xmlNode, description, loadConfigurationOptions, handleIncomingConfiguration, !skipConsoleConfig);
|
||||
configMember.performConfigurationRetrieve();
|
||||
XmlElement elem = (XmlElement)xmlNode;
|
||||
string name = elem.GetAttribute("Name");
|
||||
string xmlstr = "<Nini>" + xmlNode.OuterXml + "</Nini>";
|
||||
XmlConfigSource source = new XmlConfigSource(XmlReader.Create(new StringReader(xmlstr)));
|
||||
ReadNiniConfig(source, name);
|
||||
|
||||
m_serverURI = string.Empty;
|
||||
}
|
||||
|
||||
@@ -325,6 +342,11 @@ namespace OpenSim.Framework
|
||||
get { return m_objectCapacity; }
|
||||
}
|
||||
|
||||
public int MaxPrimsPerUser
|
||||
{
|
||||
get { return m_maxPrimsPerUser; }
|
||||
}
|
||||
|
||||
public int LinksetCapacity
|
||||
{
|
||||
get { return m_linksetCapacity; }
|
||||
@@ -349,6 +371,8 @@ namespace OpenSim.Framework
|
||||
{
|
||||
get { return m_maptileStaticUUID; }
|
||||
}
|
||||
|
||||
public string MaptileStaticFile { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The port by which http communication occurs with the region (most noticeably, CAPS communication)
|
||||
@@ -498,20 +522,20 @@ namespace OpenSim.Framework
|
||||
m_internalEndPoint = tmpEPE;
|
||||
}
|
||||
|
||||
public string GetOtherSetting(string key)
|
||||
public string GetSetting(string key)
|
||||
{
|
||||
string val;
|
||||
string keylower = key.ToLower();
|
||||
if (m_otherSettings.TryGetValue(keylower, out val))
|
||||
if (m_extraSettings.TryGetValue(keylower, out val))
|
||||
return val;
|
||||
m_log.DebugFormat("[RegionInfo] Could not locate value for parameter {0}", key);
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetOtherSetting(string key, string value)
|
||||
private void SetExtraSetting(string key, string value)
|
||||
{
|
||||
string keylower = key.ToLower();
|
||||
m_otherSettings[keylower] = value;
|
||||
m_extraSettings[keylower] = value;
|
||||
}
|
||||
|
||||
private void ReadNiniConfig(IConfigSource source, string name)
|
||||
@@ -707,6 +731,9 @@ namespace OpenSim.Framework
|
||||
m_objectCapacity = config.GetInt("MaxPrims", 15000);
|
||||
allKeys.Remove("MaxPrims");
|
||||
|
||||
m_maxPrimsPerUser = config.GetInt("MaxPrimsPerUser", -1);
|
||||
allKeys.Remove("MaxPrimsPerUser");
|
||||
|
||||
m_linksetCapacity = config.GetInt("LinksetPrims", 0);
|
||||
allKeys.Remove("LinksetPrims");
|
||||
|
||||
@@ -716,6 +743,9 @@ namespace OpenSim.Framework
|
||||
{
|
||||
config.Set("MaptileStaticUUID", m_maptileStaticUUID.ToString());
|
||||
}
|
||||
|
||||
MaptileStaticFile = config.GetString("MaptileStaticFile", String.Empty);
|
||||
allKeys.Remove("MaptileStaticFile");
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -729,7 +759,7 @@ namespace OpenSim.Framework
|
||||
|
||||
foreach (String s in allKeys)
|
||||
{
|
||||
SetOtherSetting(s, config.GetString(s));
|
||||
SetExtraSetting(s, config.GetString(s));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -829,6 +859,9 @@ namespace OpenSim.Framework
|
||||
if (m_objectCapacity > 0)
|
||||
config.Set("MaxPrims", m_objectCapacity);
|
||||
|
||||
if (m_maxPrimsPerUser > -1)
|
||||
config.Set("MaxPrimsPerUser", m_maxPrimsPerUser);
|
||||
|
||||
if (m_linksetCapacity > 0)
|
||||
config.Set("LinksetPrims", m_linksetCapacity);
|
||||
|
||||
@@ -843,6 +876,9 @@ namespace OpenSim.Framework
|
||||
|
||||
if (m_maptileStaticUUID != UUID.Zero)
|
||||
config.Set("MaptileStaticUUID", m_maptileStaticUUID.ToString());
|
||||
|
||||
if (MaptileStaticFile != String.Empty)
|
||||
config.Set("MaptileStaticFile", MaptileStaticFile);
|
||||
}
|
||||
|
||||
public bool ignoreIncomingConfiguration(string configuration_key, object configuration_result)
|
||||
@@ -869,249 +905,14 @@ namespace OpenSim.Framework
|
||||
|
||||
return;
|
||||
}
|
||||
else if (filename.ToLower().EndsWith(".xml"))
|
||||
{
|
||||
configMember = new ConfigurationMember(filename, description, loadConfigurationOptionsFromMe,
|
||||
ignoreIncomingConfiguration, false);
|
||||
configMember.performConfigurationRetrieve();
|
||||
RegionFile = filename;
|
||||
}
|
||||
else
|
||||
throw new Exception("Invalid file type for region persistence.");
|
||||
}
|
||||
|
||||
public void loadConfigurationOptionsFromMe()
|
||||
{
|
||||
configMember.addConfigurationOption("sim_UUID", ConfigurationOption.ConfigurationTypes.TYPE_UUID_NULL_FREE,
|
||||
"UUID of Region (Default is recommended, random UUID)",
|
||||
RegionID.ToString(), true);
|
||||
configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
|
||||
"Region Name", RegionName, true);
|
||||
|
||||
configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
|
||||
"Grid Location (X Axis)", RegionLocX.ToString(), true);
|
||||
configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
|
||||
"Grid Location (Y Axis)", RegionLocY.ToString(), true);
|
||||
configMember.addConfigurationOption("sim_size_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
|
||||
"Size of region in X dimension", RegionSizeX.ToString(), true);
|
||||
configMember.addConfigurationOption("sim_size_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
|
||||
"Size of region in Y dimension", RegionSizeY.ToString(), true);
|
||||
configMember.addConfigurationOption("sim_size_z", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
|
||||
"Size of region in Z dimension", RegionSizeZ.ToString(), true);
|
||||
|
||||
//m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false);
|
||||
configMember.addConfigurationOption("internal_ip_address",
|
||||
ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS,
|
||||
"Internal IP Address for incoming UDP client connections",
|
||||
m_internalEndPoint.Address.ToString(),
|
||||
true);
|
||||
configMember.addConfigurationOption("internal_ip_port", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||
"Internal IP Port for incoming UDP client connections",
|
||||
m_internalEndPoint.Port.ToString(), true);
|
||||
configMember.addConfigurationOption("allow_alternate_ports",
|
||||
ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN,
|
||||
"Allow sim to find alternate UDP ports when ports are in use?",
|
||||
m_allow_alternate_ports.ToString(), true);
|
||||
configMember.addConfigurationOption("external_host_name",
|
||||
ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
|
||||
"External Host Name", m_externalHostName, true);
|
||||
configMember.addConfigurationOption("lastmap_uuid", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
|
||||
"Last Map UUID", lastMapUUID.ToString(), true);
|
||||
configMember.addConfigurationOption("lastmap_refresh", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
|
||||
"Last Map Refresh", Util.UnixTimeSinceEpoch().ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("nonphysical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT,
|
||||
"Minimum size for nonphysical prims", m_nonphysPrimMin.ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("nonphysical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||
"Maximum size for nonphysical prims", m_nonphysPrimMax.ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("physical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT,
|
||||
"Minimum size for nonphysical prims", m_physPrimMin.ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("physical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||
"Maximum size for physical prims", m_physPrimMax.ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("clamp_prim_size", ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN,
|
||||
"Clamp prims to max size", m_clampPrimSize.ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||
"Max objects this sim will hold", m_objectCapacity.ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("linkset_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||
"Max prims an object will hold", m_linksetCapacity.ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||
"Max avatars this sim will hold", m_agentCapacity.ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("scope_id", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
|
||||
"Scope ID for this region", ScopeID.ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("region_type", ConfigurationOption.ConfigurationTypes.TYPE_STRING,
|
||||
"Free form string describing the type of region", String.Empty, true);
|
||||
|
||||
configMember.addConfigurationOption("region_static_maptile", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
|
||||
"UUID of a texture to use as the map for this region", m_maptileStaticUUID.ToString(), true);
|
||||
}
|
||||
|
||||
public void loadConfigurationOptions()
|
||||
{
|
||||
configMember.addConfigurationOption("sim_UUID", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
|
||||
"UUID of Region (Default is recommended, random UUID)",
|
||||
UUID.Random().ToString(), true);
|
||||
configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
|
||||
"Region Name", "OpenSim Test", false);
|
||||
|
||||
configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
|
||||
"Grid Location (X Axis)", "1000", false);
|
||||
configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
|
||||
"Grid Location (Y Axis)", "1000", false);
|
||||
configMember.addConfigurationOption("sim_size_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
|
||||
"Size of region in X dimension", Constants.RegionSize.ToString(), false);
|
||||
configMember.addConfigurationOption("sim_size_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
|
||||
"Size of region in Y dimension", Constants.RegionSize.ToString(), false);
|
||||
configMember.addConfigurationOption("sim_size_z", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
|
||||
"Size of region in Z dimension", Constants.RegionHeight.ToString(), false);
|
||||
|
||||
//m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false);
|
||||
configMember.addConfigurationOption("internal_ip_address",
|
||||
ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS,
|
||||
"Internal IP Address for incoming UDP client connections", "0.0.0.0",
|
||||
false);
|
||||
configMember.addConfigurationOption("internal_ip_port", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||
"Internal IP Port for incoming UDP client connections",
|
||||
ConfigSettings.DefaultRegionHttpPort.ToString(), false);
|
||||
configMember.addConfigurationOption("allow_alternate_ports", ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN,
|
||||
"Allow sim to find alternate UDP ports when ports are in use?",
|
||||
"false", true);
|
||||
configMember.addConfigurationOption("external_host_name",
|
||||
ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
|
||||
"External Host Name", "127.0.0.1", false);
|
||||
configMember.addConfigurationOption("lastmap_uuid", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
|
||||
"Last Map UUID", lastMapUUID.ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("lastmap_refresh", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
|
||||
"Last Map Refresh", Util.UnixTimeSinceEpoch().ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("nonphysical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||
"Maximum size for nonphysical prims", "0", true);
|
||||
|
||||
configMember.addConfigurationOption("physical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||
"Maximum size for physical prims", "0", true);
|
||||
|
||||
configMember.addConfigurationOption("clamp_prim_size", ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN,
|
||||
"Clamp prims to max size", "false", true);
|
||||
|
||||
configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||
"Max objects this sim will hold", "15000", true);
|
||||
|
||||
configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||
"Max avatars this sim will hold", "100", true);
|
||||
|
||||
configMember.addConfigurationOption("scope_id", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
|
||||
"Scope ID for this region", UUID.Zero.ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("region_type", ConfigurationOption.ConfigurationTypes.TYPE_STRING,
|
||||
"Region Type", String.Empty, true);
|
||||
|
||||
configMember.addConfigurationOption("region_static_maptile", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
|
||||
"UUID of a texture to use as the map for this region", String.Empty, true);
|
||||
}
|
||||
|
||||
public bool handleIncomingConfiguration(string configuration_key, object configuration_result)
|
||||
{
|
||||
switch (configuration_key)
|
||||
{
|
||||
case "sim_UUID":
|
||||
RegionID = (UUID) configuration_result;
|
||||
originRegionID = (UUID) configuration_result;
|
||||
break;
|
||||
case "sim_name":
|
||||
RegionName = (string) configuration_result;
|
||||
break;
|
||||
case "sim_location_x":
|
||||
RegionLocX = (uint) configuration_result;
|
||||
break;
|
||||
case "sim_location_y":
|
||||
RegionLocY = (uint) configuration_result;
|
||||
break;
|
||||
case "sim_size_x":
|
||||
RegionSizeX = (uint) configuration_result;
|
||||
break;
|
||||
case "sim_size_y":
|
||||
RegionSizeY = (uint) configuration_result;
|
||||
break;
|
||||
case "sim_size_z":
|
||||
RegionSizeZ = (uint) configuration_result;
|
||||
break;
|
||||
case "internal_ip_address":
|
||||
IPAddress address = (IPAddress) configuration_result;
|
||||
m_internalEndPoint = new IPEndPoint(address, 0);
|
||||
break;
|
||||
case "internal_ip_port":
|
||||
m_internalEndPoint.Port = (int) configuration_result;
|
||||
break;
|
||||
case "allow_alternate_ports":
|
||||
m_allow_alternate_ports = (bool) configuration_result;
|
||||
break;
|
||||
case "external_host_name":
|
||||
if ((string) configuration_result != "SYSTEMIP")
|
||||
{
|
||||
m_externalHostName = (string) configuration_result;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_externalHostName = Util.GetLocalHost().ToString();
|
||||
}
|
||||
break;
|
||||
case "lastmap_uuid":
|
||||
lastMapUUID = (UUID)configuration_result;
|
||||
break;
|
||||
case "lastmap_refresh":
|
||||
lastMapRefresh = (string)configuration_result;
|
||||
break;
|
||||
case "nonphysical_prim_max":
|
||||
m_nonphysPrimMax = (int)configuration_result;
|
||||
break;
|
||||
case "physical_prim_max":
|
||||
m_physPrimMax = (int)configuration_result;
|
||||
break;
|
||||
case "clamp_prim_size":
|
||||
m_clampPrimSize = (bool)configuration_result;
|
||||
break;
|
||||
case "object_capacity":
|
||||
m_objectCapacity = (int)configuration_result;
|
||||
break;
|
||||
case "linkset_capacity":
|
||||
m_linksetCapacity = (int)configuration_result;
|
||||
break;
|
||||
case "agent_capacity":
|
||||
m_agentCapacity = (int)configuration_result;
|
||||
break;
|
||||
case "scope_id":
|
||||
ScopeID = (UUID)configuration_result;
|
||||
break;
|
||||
case "region_type":
|
||||
m_regionType = (string)configuration_result;
|
||||
break;
|
||||
case "region_static_maptile":
|
||||
m_maptileStaticUUID = (UUID)configuration_result;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SaveLastMapUUID(UUID mapUUID)
|
||||
{
|
||||
lastMapUUID = mapUUID;
|
||||
lastMapRefresh = Util.UnixTimeSinceEpoch().ToString();
|
||||
|
||||
if (configMember == null)
|
||||
return;
|
||||
|
||||
configMember.forceSetConfigurationOption("lastmap_uuid", mapUUID.ToString());
|
||||
configMember.forceSetConfigurationOption("lastmap_refresh", lastMapRefresh);
|
||||
}
|
||||
|
||||
public OSDMap PackRegionInfoData()
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace OpenSim.Framework.RegionLoader.Web
|
||||
xmlSource.Length);
|
||||
XmlDocument xmlDoc = new XmlDocument();
|
||||
xmlDoc.LoadXml(xmlSource);
|
||||
if (xmlDoc.FirstChild.Name == "Regions")
|
||||
if (xmlDoc.FirstChild.Name == "Nini")
|
||||
{
|
||||
regionCount = xmlDoc.FirstChild.ChildNodes.Count;
|
||||
|
||||
@@ -144,4 +144,4 @@ namespace OpenSim.Framework.RegionLoader.Web
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
@@ -161,7 +161,7 @@ namespace OpenSim.Framework.Serialization.External
|
||||
if (!hasCreatorData && creator != null)
|
||||
{
|
||||
XmlElement creatorData = doc.CreateElement("CreatorData");
|
||||
creatorData.InnerText = homeURL + ";" + creator.FirstName + " " + creator.LastName;
|
||||
creatorData.InnerText = CalcCreatorData(homeURL, creator.FirstName + " " + creator.LastName);
|
||||
sop.AppendChild(creatorData);
|
||||
}
|
||||
}
|
||||
@@ -172,5 +172,15 @@ namespace OpenSim.Framework.Serialization.External
|
||||
return wr.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public static string CalcCreatorData(string homeURL, string name)
|
||||
{
|
||||
return homeURL + ";" + name;
|
||||
}
|
||||
|
||||
internal static string CalcCreatorData(string homeURL, UUID uuid, string name)
|
||||
{
|
||||
return homeURL + "/" + uuid + ";" + name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,8 +213,13 @@ namespace OpenSim.Framework.Serialization.External
|
||||
xtw.WriteElementString("ClaimDate", Convert.ToString(landData.ClaimDate));
|
||||
xtw.WriteElementString("ClaimPrice", Convert.ToString(landData.ClaimPrice));
|
||||
xtw.WriteElementString("GlobalID", landData.GlobalID.ToString());
|
||||
xtw.WriteElementString("GroupID", landData.GroupID.ToString());
|
||||
xtw.WriteElementString("IsGroupOwned", Convert.ToString(landData.IsGroupOwned));
|
||||
|
||||
UUID groupID = options.ContainsKey("wipe-owners") ? UUID.Zero : landData.GroupID;
|
||||
xtw.WriteElementString("GroupID", groupID.ToString());
|
||||
|
||||
bool isGroupOwned = options.ContainsKey("wipe-owners") ? false : landData.IsGroupOwned;
|
||||
xtw.WriteElementString("IsGroupOwned", Convert.ToString(isGroupOwned));
|
||||
|
||||
xtw.WriteElementString("Bitmap", Convert.ToBase64String(landData.Bitmap));
|
||||
xtw.WriteElementString("Description", landData.Description);
|
||||
xtw.WriteElementString("Flags", Convert.ToString((uint)landData.Flags));
|
||||
@@ -227,13 +232,8 @@ namespace OpenSim.Framework.Serialization.External
|
||||
xtw.WriteElementString("MediaURL", landData.MediaURL);
|
||||
xtw.WriteElementString("MusicURL", landData.MusicURL);
|
||||
|
||||
UUID ownerIdToWrite;
|
||||
if (options != null && options.ContainsKey("wipe-owners"))
|
||||
ownerIdToWrite = UUID.Zero;
|
||||
else
|
||||
ownerIdToWrite = landData.OwnerID;
|
||||
|
||||
xtw.WriteElementString("OwnerID", ownerIdToWrite.ToString());
|
||||
UUID ownerID = options.ContainsKey("wipe-owners") ? UUID.Zero : landData.OwnerID;
|
||||
xtw.WriteElementString("OwnerID", ownerID.ToString());
|
||||
|
||||
xtw.WriteStartElement("ParcelAccessList");
|
||||
foreach (LandAccessEntry pal in landData.ParcelAccessList)
|
||||
|
||||
@@ -286,7 +286,8 @@ namespace OpenSim.Framework.Serialization.External
|
||||
UserAccount account = userAccountService.GetUserAccount(UUID.Zero, inventoryItem.CreatorIdAsUuid);
|
||||
if (account != null)
|
||||
{
|
||||
writer.WriteElementString("CreatorData", (string)options["home"] + "/" + inventoryItem.CreatorIdAsUuid + ";" + account.FirstName + " " + account.LastName);
|
||||
string creatorData = ExternalRepresentationUtils.CalcCreatorData((string)options["home"], inventoryItem.CreatorIdAsUuid, account.FirstName + " " + account.LastName);
|
||||
writer.WriteElementString("CreatorData", creatorData);
|
||||
}
|
||||
writer.WriteElementString("CreatorID", inventoryItem.CreatorId);
|
||||
}
|
||||
|
||||
@@ -121,7 +121,8 @@ namespace OpenSim.Framework.Serialization.Tests
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
LandData ld = LandDataSerializer.Deserialize(LandDataSerializer.Serialize(this.land, null));
|
||||
Dictionary<string, object> options = new Dictionary<string, object>();
|
||||
LandData ld = LandDataSerializer.Deserialize(LandDataSerializer.Serialize(this.land, options));
|
||||
Assert.That(ld, Is.Not.Null, "Deserialize(string) returned null");
|
||||
// Assert.That(ld.AABBMax, Is.EqualTo(land.AABBMax));
|
||||
// Assert.That(ld.AABBMin, Is.EqualTo(land.AABBMin));
|
||||
|
||||
@@ -46,6 +46,7 @@ using CoolHTTPListener = HttpServer.HttpListener;
|
||||
using HttpListener=System.Net.HttpListener;
|
||||
using LogPrio=HttpServer.LogPrio;
|
||||
using OpenSim.Framework.Monitoring;
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
@@ -113,7 +114,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
protected IPAddress m_listenIPAddress = IPAddress.Any;
|
||||
|
||||
private PollServiceRequestManager m_PollServiceManager;
|
||||
public PollServiceRequestManager PollServiceRequestManager { get; private set; }
|
||||
|
||||
public uint SSLPort
|
||||
{
|
||||
@@ -374,7 +375,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnRequest(object source, RequestEventArgs args)
|
||||
public void OnRequest(object source, RequestEventArgs args)
|
||||
{
|
||||
RequestNumber++;
|
||||
|
||||
@@ -429,7 +430,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
psEvArgs.Request(psreq.RequestID, keysvals);
|
||||
}
|
||||
|
||||
m_PollServiceManager.Enqueue(psreq);
|
||||
PollServiceRequestManager.Enqueue(psreq);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -491,8 +492,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
try
|
||||
{
|
||||
byte[] buffer500 = SendHTML500(response);
|
||||
response.Body.Write(buffer500,0,buffer500.Length);
|
||||
response.Body.Close();
|
||||
response.OutputStream.Write(buffer500, 0, buffer500.Length);
|
||||
response.Send();
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -690,6 +691,23 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
if (buffer != null)
|
||||
{
|
||||
if (WebUtil.DebugLevel >= 5)
|
||||
{
|
||||
string output = System.Text.Encoding.UTF8.GetString(buffer);
|
||||
|
||||
if (WebUtil.DebugLevel >= 6)
|
||||
{
|
||||
// Always truncate binary blobs. We don't have a ContentType, so detect them using the request name.
|
||||
if ((requestHandler != null && requestHandler.Name == "GetMesh"))
|
||||
{
|
||||
if (output.Length > WebUtil.MaxRequestDiagLength)
|
||||
output = output.Substring(0, WebUtil.MaxRequestDiagLength) + "...";
|
||||
}
|
||||
}
|
||||
|
||||
WebUtil.LogResponseDetail(RequestNumber, output);
|
||||
}
|
||||
|
||||
if (!response.SendChunked && response.ContentLength64 <= 0)
|
||||
response.ContentLength64 = buffer.LongLength;
|
||||
|
||||
@@ -720,16 +738,16 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e);
|
||||
m_log.Error("[BASE HTTP SERVER]: HandleRequest() threw exception ", e);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e);
|
||||
m_log.Error("[BASE HTTP SERVER]: HandleRequest() threw exception ", e);
|
||||
try
|
||||
{
|
||||
byte[] buffer500 = SendHTML500(response);
|
||||
response.Body.Write(buffer500, 0, buffer500.Length);
|
||||
response.Body.Close();
|
||||
response.OutputStream.Write(buffer500, 0, buffer500.Length);
|
||||
response.Send();
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -743,7 +761,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
if (tickdiff > 3000 && requestHandler != null && requestHandler.Name != "GetTexture")
|
||||
{
|
||||
m_log.InfoFormat(
|
||||
"[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms",
|
||||
"[LOGHTTP] Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms",
|
||||
RequestNumber,
|
||||
requestMethod,
|
||||
uriString,
|
||||
@@ -755,7 +773,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
else if (DebugLevel >= 4)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: HTTP IN {0} :{1} took {2}ms",
|
||||
"[LOGHTTP] HTTP IN {0} :{1} took {2}ms",
|
||||
RequestNumber,
|
||||
Port,
|
||||
tickdiff);
|
||||
@@ -766,7 +784,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
private void LogIncomingToStreamHandler(OSHttpRequest request, IRequestHandler requestHandler)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: HTTP IN {0} :{1} stream handler {2} {3} {4} {5} from {6}",
|
||||
"[LOGHTTP] HTTP IN {0} :{1} stream handler {2} {3} {4} {5} from {6}",
|
||||
RequestNumber,
|
||||
Port,
|
||||
request.HttpMethod,
|
||||
@@ -782,7 +800,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
private void LogIncomingToContentTypeHandler(OSHttpRequest request)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}",
|
||||
"[LOGHTTP] HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}",
|
||||
RequestNumber,
|
||||
Port,
|
||||
string.IsNullOrEmpty(request.ContentType) ? "not set" : request.ContentType,
|
||||
@@ -797,7 +815,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
private void LogIncomingToXmlRpcHandler(OSHttpRequest request)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: HTTP IN {0} :{1} assumed generic XMLRPC request {2} {3} from {4}",
|
||||
"[LOGHTTP] HTTP IN {0} :{1} assumed generic XMLRPC request {2} {3} from {4}",
|
||||
RequestNumber,
|
||||
Port,
|
||||
request.HttpMethod,
|
||||
@@ -810,29 +828,37 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
private void LogIncomingInDetail(OSHttpRequest request)
|
||||
{
|
||||
using (StreamReader reader = new StreamReader(Util.Copy(request.InputStream), Encoding.UTF8))
|
||||
if (request.ContentType == "application/octet-stream")
|
||||
return; // never log these; they're just binary data
|
||||
|
||||
Stream inputStream = Util.Copy(request.InputStream);
|
||||
|
||||
if ((request.Headers["Content-Encoding"] == "gzip") || (request.Headers["X-Content-Encoding"] == "gzip"))
|
||||
inputStream = new GZipStream(inputStream, System.IO.Compression.CompressionMode.Decompress);
|
||||
|
||||
using (StreamReader reader = new StreamReader(inputStream, Encoding.UTF8))
|
||||
{
|
||||
string output;
|
||||
|
||||
if (DebugLevel == 5)
|
||||
{
|
||||
const int sampleLength = 80;
|
||||
char[] sampleChars = new char[sampleLength + 3];
|
||||
reader.Read(sampleChars, 0, sampleLength);
|
||||
sampleChars[80] = '.';
|
||||
sampleChars[81] = '.';
|
||||
sampleChars[82] = '.';
|
||||
output = new string(sampleChars);
|
||||
char[] chars = new char[WebUtil.MaxRequestDiagLength + 1]; // +1 so we know to add "..." only if needed
|
||||
int len = reader.Read(chars, 0, WebUtil.MaxRequestDiagLength + 1);
|
||||
output = new string(chars, 0, Math.Min(len, WebUtil.MaxRequestDiagLength));
|
||||
if (len > WebUtil.MaxRequestDiagLength)
|
||||
output += "...";
|
||||
}
|
||||
else
|
||||
{
|
||||
output = reader.ReadToEnd();
|
||||
}
|
||||
|
||||
m_log.DebugFormat("[BASE HTTP SERVER]: {0}", output.Replace("\n", @"\n"));
|
||||
m_log.DebugFormat("[LOGHTTP] {0}", Util.BinaryToASCII(output));
|
||||
}
|
||||
}
|
||||
|
||||
private readonly string HANDLER_SEPARATORS = "/?&#-";
|
||||
|
||||
private bool TryGetStreamHandler(string handlerKey, out IRequestHandler streamHandler)
|
||||
{
|
||||
string bestMatch = null;
|
||||
@@ -841,7 +867,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
foreach (string pattern in m_streamHandlers.Keys)
|
||||
{
|
||||
if (handlerKey.StartsWith(pattern))
|
||||
if ((handlerKey == pattern)
|
||||
|| (handlerKey.StartsWith(pattern) && (HANDLER_SEPARATORS.IndexOf(handlerKey[pattern.Length]) >= 0)))
|
||||
{
|
||||
if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length)
|
||||
{
|
||||
@@ -871,7 +898,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
foreach (string pattern in m_pollHandlers.Keys)
|
||||
{
|
||||
if (handlerKey.StartsWith(pattern))
|
||||
if ((handlerKey == pattern)
|
||||
|| (handlerKey.StartsWith(pattern) && (HANDLER_SEPARATORS.IndexOf(handlerKey[pattern.Length]) >= 0)))
|
||||
{
|
||||
if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length)
|
||||
{
|
||||
@@ -903,7 +931,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
foreach (string pattern in m_HTTPHandlers.Keys)
|
||||
{
|
||||
if (handlerKey.StartsWith(pattern))
|
||||
if ((handlerKey == pattern)
|
||||
|| (handlerKey.StartsWith(pattern) && (HANDLER_SEPARATORS.IndexOf(handlerKey[pattern.Length]) >= 0)))
|
||||
{
|
||||
if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length)
|
||||
{
|
||||
@@ -954,6 +983,9 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
Stream requestStream = request.InputStream;
|
||||
|
||||
if ((request.Headers["Content-Encoding"] == "gzip") || (request.Headers["X-Content-Encoding"] == "gzip"))
|
||||
requestStream = new GZipStream(requestStream, System.IO.Compression.CompressionMode.Decompress);
|
||||
|
||||
Encoding encoding = Encoding.UTF8;
|
||||
StreamReader reader = new StreamReader(requestStream, encoding);
|
||||
|
||||
@@ -1781,10 +1813,17 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
public void Start()
|
||||
{
|
||||
StartHTTP();
|
||||
Start(true);
|
||||
}
|
||||
|
||||
private void StartHTTP()
|
||||
/// <summary>
|
||||
/// Start the http server
|
||||
/// </summary>
|
||||
/// <param name='processPollRequestsAsync'>
|
||||
/// If true then poll responses are performed asynchronsly.
|
||||
/// Option exists to allow regression tests to perform processing synchronously.
|
||||
/// </param>
|
||||
public void Start(bool performPollResponsesAsync)
|
||||
{
|
||||
m_log.InfoFormat(
|
||||
"[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port);
|
||||
@@ -1822,8 +1861,9 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
m_httpListener2.Start(64);
|
||||
|
||||
// Long Poll Service Manager with 3 worker threads a 25 second timeout for no events
|
||||
m_PollServiceManager = new PollServiceRequestManager(this, 3, 25000);
|
||||
m_PollServiceManager.Start();
|
||||
PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 3, 25000);
|
||||
PollServiceRequestManager.Start();
|
||||
|
||||
HTTPDRunning = true;
|
||||
|
||||
//HttpListenerContext context;
|
||||
@@ -1892,7 +1932,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
try
|
||||
{
|
||||
m_PollServiceManager.Stop();
|
||||
PollServiceRequestManager.Stop();
|
||||
|
||||
m_httpListener2.ExceptionThrown -= httpServerException;
|
||||
//m_httpListener2.DisconnectHandler = null;
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using OpenSim.Framework.ServiceAuth;
|
||||
|
||||
namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
@@ -37,15 +39,30 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
/// </remarks>
|
||||
public abstract class BaseStreamHandler : BaseRequestHandler, IStreamedRequestHandler
|
||||
{
|
||||
protected BaseStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
|
||||
protected IServiceAuth m_Auth;
|
||||
|
||||
protected BaseStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) { }
|
||||
|
||||
protected BaseStreamHandler(string httpMethod, string path, string name, string description)
|
||||
: base(httpMethod, path, name, description) {}
|
||||
|
||||
protected BaseStreamHandler(string httpMethod, string path, IServiceAuth auth)
|
||||
: base(httpMethod, path, null, null)
|
||||
{
|
||||
m_Auth = auth;
|
||||
}
|
||||
|
||||
public virtual byte[] Handle(
|
||||
string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
RequestsReceived++;
|
||||
if (m_Auth != null && !m_Auth.Authenticate(httpRequest.Headers, httpResponse.AddHeader))
|
||||
{
|
||||
|
||||
httpResponse.StatusCode = (int)HttpStatusCode.Unauthorized;
|
||||
httpResponse.ContentType = "text/plain";
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
byte[] result = ProcessRequest(path, request, httpRequest, httpResponse);
|
||||
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using OpenMetaverse;
|
||||
using log4net;
|
||||
|
||||
namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
/// <summary>
|
||||
/// Json rpc request manager.
|
||||
/// </summary>
|
||||
public class JsonRpcRequestManager
|
||||
{
|
||||
static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public JsonRpcRequestManager()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends json-rpc request with a serializable type.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// OSD Map.
|
||||
/// </returns>
|
||||
/// <param name='parameters'>
|
||||
/// Serializable type .
|
||||
/// </param>
|
||||
/// <param name='method'>
|
||||
/// Json-rpc method to call.
|
||||
/// </param>
|
||||
/// <param name='uri'>
|
||||
/// URI of json-rpc service.
|
||||
/// </param>
|
||||
/// <param name='jsonId'>
|
||||
/// Id for our call.
|
||||
/// </param>
|
||||
public bool JsonRpcRequest(ref object parameters, string method, string uri, string jsonId)
|
||||
{
|
||||
if (jsonId == null)
|
||||
throw new ArgumentNullException("jsonId");
|
||||
if (uri == null)
|
||||
throw new ArgumentNullException("uri");
|
||||
if (method == null)
|
||||
throw new ArgumentNullException("method");
|
||||
if (parameters == null)
|
||||
throw new ArgumentNullException("parameters");
|
||||
|
||||
OSDMap request = new OSDMap();
|
||||
request.Add("jsonrpc", OSD.FromString("2.0"));
|
||||
request.Add("id", OSD.FromString(jsonId));
|
||||
request.Add("method", OSD.FromString(method));
|
||||
request.Add("params", OSD.SerializeMembers(parameters));
|
||||
|
||||
OSDMap response;
|
||||
try
|
||||
{
|
||||
response = WebUtil.PostToService(uri, request, 10000, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Debug(string.Format("JsonRpc request '{0}' to {1} failed", method, uri), e);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!response.ContainsKey("_Result"))
|
||||
{
|
||||
m_log.DebugFormat("JsonRpc request '{0}' to {1} returned an invalid response: {2}",
|
||||
method, uri, OSDParser.SerializeJsonString(response));
|
||||
return false;
|
||||
}
|
||||
response = (OSDMap)response["_Result"];
|
||||
|
||||
OSD data;
|
||||
|
||||
if (response.ContainsKey("error"))
|
||||
{
|
||||
data = response["error"];
|
||||
m_log.DebugFormat("JsonRpc request '{0}' to {1} returned an error: {2}",
|
||||
method, uri, OSDParser.SerializeJsonString(data));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!response.ContainsKey("result"))
|
||||
{
|
||||
m_log.DebugFormat("JsonRpc request '{0}' to {1} returned an invalid response: {2}",
|
||||
method, uri, OSDParser.SerializeJsonString(response));
|
||||
return false;
|
||||
}
|
||||
|
||||
data = response["result"];
|
||||
OSD.DeserializeMembers(ref parameters, (OSDMap)data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends json-rpc request with OSD parameter.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The rpc request.
|
||||
/// </returns>
|
||||
/// <param name='data'>
|
||||
/// data - incoming as parameters, outgoing as result/error
|
||||
/// </param>
|
||||
/// <param name='method'>
|
||||
/// Json-rpc method to call.
|
||||
/// </param>
|
||||
/// <param name='uri'>
|
||||
/// URI of json-rpc service.
|
||||
/// </param>
|
||||
/// <param name='jsonId'>
|
||||
/// If set to <c>true</c> json identifier.
|
||||
/// </param>
|
||||
public bool JsonRpcRequest(ref OSD data, string method, string uri, string jsonId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(jsonId))
|
||||
jsonId = UUID.Random().ToString();
|
||||
|
||||
OSDMap request = new OSDMap();
|
||||
request.Add("jsonrpc", OSD.FromString("2.0"));
|
||||
request.Add("id", OSD.FromString(jsonId));
|
||||
request.Add("method", OSD.FromString(method));
|
||||
request.Add("params", data);
|
||||
|
||||
OSDMap response;
|
||||
try
|
||||
{
|
||||
response = WebUtil.PostToService(uri, request, 10000, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Debug(string.Format("JsonRpc request '{0}' to {1} failed", method, uri), e);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!response.ContainsKey("_Result"))
|
||||
{
|
||||
m_log.DebugFormat("JsonRpc request '{0}' to {1} returned an invalid response: {2}",
|
||||
method, uri, OSDParser.SerializeJsonString(response));
|
||||
return false;
|
||||
}
|
||||
response = (OSDMap)response["_Result"];
|
||||
|
||||
if (response.ContainsKey("error"))
|
||||
{
|
||||
data = response["error"];
|
||||
m_log.DebugFormat("JsonRpc request '{0}' to {1} returned an error: {2}",
|
||||
method, uri, OSDParser.SerializeJsonString(data));
|
||||
return false;
|
||||
}
|
||||
|
||||
data = response;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -182,11 +182,22 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
_context = context;
|
||||
|
||||
if (null != req.Headers["content-encoding"])
|
||||
_contentEncoding = Encoding.GetEncoding(_request.Headers["content-encoding"]);
|
||||
{
|
||||
try
|
||||
{
|
||||
_contentEncoding = Encoding.GetEncoding(_request.Headers["content-encoding"]);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
if (null != req.Headers["content-type"])
|
||||
_contentType = _request.Headers["content-type"];
|
||||
if (null != req.Headers["user-agent"])
|
||||
_userAgent = req.Headers["user-agent"];
|
||||
|
||||
if (null != req.Headers["remote_addr"])
|
||||
{
|
||||
try
|
||||
|
||||
@@ -44,6 +44,25 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
/// <summary>
|
||||
/// Is the poll service request manager running?
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Can be running either synchronously or asynchronously
|
||||
/// </remarks>
|
||||
public bool IsRunning { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is the poll service performing responses asynchronously (with its own threads) or synchronously (via
|
||||
/// external calls)?
|
||||
/// </summary>
|
||||
public bool PerformResponsesAsync { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of responses actually processed and sent to viewer (or aborted due to error).
|
||||
/// </summary>
|
||||
public int ResponsesProcessed { get; private set; }
|
||||
|
||||
private readonly BaseHttpServer m_server;
|
||||
|
||||
private BlockingQueue<PollServiceHttpRequest> m_requests = new BlockingQueue<PollServiceHttpRequest>();
|
||||
@@ -52,48 +71,79 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
private uint m_WorkerThreadCount = 0;
|
||||
private Thread[] m_workerThreads;
|
||||
|
||||
private bool m_running = true;
|
||||
|
||||
private SmartThreadPool m_threadPool = new SmartThreadPool(20000, 12, 2);
|
||||
|
||||
// private int m_timeout = 1000; // increase timeout 250; now use the event one
|
||||
|
||||
public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout)
|
||||
public PollServiceRequestManager(
|
||||
BaseHttpServer pSrv, bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout)
|
||||
{
|
||||
m_server = pSrv;
|
||||
PerformResponsesAsync = performResponsesAsync;
|
||||
m_WorkerThreadCount = pWorkerThreadCount;
|
||||
m_workerThreads = new Thread[m_WorkerThreadCount];
|
||||
|
||||
StatsManager.RegisterStat(
|
||||
new Stat(
|
||||
"QueuedPollResponses",
|
||||
"Number of poll responses queued for processing.",
|
||||
"",
|
||||
"",
|
||||
"httpserver",
|
||||
m_server.Port.ToString(),
|
||||
StatType.Pull,
|
||||
MeasuresOfInterest.AverageChangeOverTime,
|
||||
stat => stat.Value = m_requests.Count(),
|
||||
StatVerbosity.Debug));
|
||||
|
||||
StatsManager.RegisterStat(
|
||||
new Stat(
|
||||
"ProcessedPollResponses",
|
||||
"Number of poll responses processed.",
|
||||
"",
|
||||
"",
|
||||
"httpserver",
|
||||
m_server.Port.ToString(),
|
||||
StatType.Pull,
|
||||
MeasuresOfInterest.AverageChangeOverTime,
|
||||
stat => stat.Value = ResponsesProcessed,
|
||||
StatVerbosity.Debug));
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
//startup worker threads
|
||||
for (uint i = 0; i < m_WorkerThreadCount; i++)
|
||||
{
|
||||
m_workerThreads[i]
|
||||
= Watchdog.StartThread(
|
||||
PoolWorkerJob,
|
||||
string.Format("PollServiceWorkerThread{0}:{1}", i, m_server.Port),
|
||||
ThreadPriority.Normal,
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
int.MaxValue);
|
||||
}
|
||||
IsRunning = true;
|
||||
|
||||
Watchdog.StartThread(
|
||||
this.CheckLongPollThreads,
|
||||
string.Format("LongPollServiceWatcherThread:{0}", m_server.Port),
|
||||
ThreadPriority.Normal,
|
||||
false,
|
||||
true,
|
||||
null,
|
||||
1000 * 60 * 10);
|
||||
if (PerformResponsesAsync)
|
||||
{
|
||||
//startup worker threads
|
||||
for (uint i = 0; i < m_WorkerThreadCount; i++)
|
||||
{
|
||||
m_workerThreads[i]
|
||||
= Watchdog.StartThread(
|
||||
PoolWorkerJob,
|
||||
string.Format("PollServiceWorkerThread{0}:{1}", i, m_server.Port),
|
||||
ThreadPriority.Normal,
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
int.MaxValue);
|
||||
}
|
||||
|
||||
Watchdog.StartThread(
|
||||
this.CheckLongPollThreads,
|
||||
string.Format("LongPollServiceWatcherThread:{0}", m_server.Port),
|
||||
ThreadPriority.Normal,
|
||||
false,
|
||||
true,
|
||||
null,
|
||||
1000 * 60 * 10);
|
||||
}
|
||||
}
|
||||
|
||||
private void ReQueueEvent(PollServiceHttpRequest req)
|
||||
{
|
||||
if (m_running)
|
||||
if (IsRunning)
|
||||
{
|
||||
// delay the enqueueing for 100ms. There's no need to have the event
|
||||
// actively on the queue
|
||||
@@ -109,7 +159,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
public void Enqueue(PollServiceHttpRequest req)
|
||||
{
|
||||
if (m_running)
|
||||
if (IsRunning)
|
||||
{
|
||||
if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll)
|
||||
{
|
||||
@@ -129,7 +179,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
// All other types of tasks (Inventory handlers, http-in, etc) don't have the long-poll nature,
|
||||
// so if they aren't ready to be served by a worker thread (no events), they are placed
|
||||
// directly back in the "ready-to-serve" queue by the worker thread.
|
||||
while (m_running)
|
||||
while (IsRunning)
|
||||
{
|
||||
Thread.Sleep(500);
|
||||
Watchdog.UpdateThread();
|
||||
@@ -137,7 +187,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
// List<PollServiceHttpRequest> not_ready = new List<PollServiceHttpRequest>();
|
||||
lock (m_longPollRequests)
|
||||
{
|
||||
if (m_longPollRequests.Count > 0 && m_running)
|
||||
if (m_longPollRequests.Count > 0 && IsRunning)
|
||||
{
|
||||
List<PollServiceHttpRequest> ready = m_longPollRequests.FindAll(req =>
|
||||
(req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id) || // there are events in this EQ
|
||||
@@ -158,7 +208,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
m_running = false;
|
||||
IsRunning = false;
|
||||
// m_timeout = -10000; // cause all to expire
|
||||
Thread.Sleep(1000); // let the world move
|
||||
|
||||
@@ -169,7 +219,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
lock (m_longPollRequests)
|
||||
{
|
||||
if (m_longPollRequests.Count > 0 && m_running)
|
||||
if (m_longPollRequests.Count > 0 && IsRunning)
|
||||
m_longPollRequests.ForEach(req => m_requests.Enqueue(req));
|
||||
}
|
||||
|
||||
@@ -178,6 +228,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
try
|
||||
{
|
||||
wreq = m_requests.Dequeue(0);
|
||||
ResponsesProcessed++;
|
||||
wreq.DoHTTPGruntWork(
|
||||
m_server, wreq.PollServiceArgs.NoEvents(wreq.RequestID, wreq.PollServiceArgs.Id));
|
||||
}
|
||||
@@ -194,69 +245,86 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
private void PoolWorkerJob()
|
||||
{
|
||||
while (m_running)
|
||||
while (IsRunning)
|
||||
{
|
||||
PollServiceHttpRequest req = m_requests.Dequeue(5000);
|
||||
//m_log.WarnFormat("[YYY]: Dequeued {0}", (req == null ? "null" : req.PollServiceArgs.Type.ToString()));
|
||||
|
||||
Watchdog.UpdateThread();
|
||||
if (req != null)
|
||||
WaitPerformResponse();
|
||||
}
|
||||
}
|
||||
|
||||
public void WaitPerformResponse()
|
||||
{
|
||||
PollServiceHttpRequest req = m_requests.Dequeue(5000);
|
||||
// m_log.DebugFormat("[YYY]: Dequeued {0}", (req == null ? "null" : req.PollServiceArgs.Type.ToString()));
|
||||
|
||||
if (req != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
|
||||
{
|
||||
if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
|
||||
Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
|
||||
|
||||
if (responsedata == null)
|
||||
return;
|
||||
|
||||
// This is the event queue.
|
||||
// Even if we're not running we can still perform responses by explicit request.
|
||||
if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll
|
||||
|| !PerformResponsesAsync)
|
||||
{
|
||||
Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
|
||||
|
||||
if (responsedata == null)
|
||||
continue;
|
||||
|
||||
if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll) // This is the event queue
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
req.DoHTTPGruntWork(m_server, responsedata);
|
||||
}
|
||||
catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
|
||||
{
|
||||
// Ignore it, no need to reply
|
||||
}
|
||||
ResponsesProcessed++;
|
||||
req.DoHTTPGruntWork(m_server, responsedata);
|
||||
}
|
||||
else
|
||||
catch (ObjectDisposedException e) // Browser aborted before we could read body, server closed the stream
|
||||
{
|
||||
m_threadPool.QueueWorkItem(x =>
|
||||
{
|
||||
try
|
||||
{
|
||||
req.DoHTTPGruntWork(m_server, responsedata);
|
||||
}
|
||||
catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
|
||||
{
|
||||
// Ignore it, no need to reply
|
||||
}
|
||||
|
||||
return null;
|
||||
}, null);
|
||||
// Ignore it, no need to reply
|
||||
m_log.Error(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
|
||||
m_threadPool.QueueWorkItem(x =>
|
||||
{
|
||||
req.DoHTTPGruntWork(
|
||||
m_server, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
|
||||
}
|
||||
else
|
||||
{
|
||||
ReQueueEvent(req);
|
||||
}
|
||||
try
|
||||
{
|
||||
ResponsesProcessed++;
|
||||
req.DoHTTPGruntWork(m_server, responsedata);
|
||||
}
|
||||
catch (ObjectDisposedException e) // Browser aborted before we could read body, server closed the stream
|
||||
{
|
||||
// Ignore it, no need to reply
|
||||
m_log.Error(e);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
else
|
||||
{
|
||||
m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
|
||||
if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
|
||||
{
|
||||
ResponsesProcessed++;
|
||||
req.DoHTTPGruntWork(
|
||||
m_server, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
|
||||
}
|
||||
else
|
||||
{
|
||||
ReQueueEvent(req);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,6 +279,17 @@ namespace OpenSim.Framework.Servers
|
||||
"debug threadpool status",
|
||||
"Show current debug threadpool parameters.",
|
||||
HandleDebugThreadpoolStatus);
|
||||
|
||||
m_console.Commands.AddCommand(
|
||||
"Debug", false, "debug threadpool level",
|
||||
"debug threadpool level 0.." + Util.MAX_THREADPOOL_LEVEL,
|
||||
"Turn on logging of activity in the main thread pool.",
|
||||
"Log levels:\n"
|
||||
+ " 0 = no logging\n"
|
||||
+ " 1 = only first line of stack trace; don't log common threads\n"
|
||||
+ " 2 = full stack trace; don't log common threads\n"
|
||||
+ " 3 = full stack trace, including common threads\n",
|
||||
HandleDebugThreadpoolLevel);
|
||||
|
||||
m_console.Commands.AddCommand(
|
||||
"Debug", false, "force gc",
|
||||
@@ -432,6 +443,33 @@ namespace OpenSim.Framework.Servers
|
||||
}
|
||||
}
|
||||
|
||||
private static void HandleDebugThreadpoolLevel(string module, string[] cmdparams)
|
||||
{
|
||||
if (cmdparams.Length < 4)
|
||||
{
|
||||
MainConsole.Instance.Output("Usage: debug threadpool level 0.." + Util.MAX_THREADPOOL_LEVEL);
|
||||
return;
|
||||
}
|
||||
|
||||
string rawLevel = cmdparams[3];
|
||||
int newLevel;
|
||||
|
||||
if (!int.TryParse(rawLevel, out newLevel))
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("{0} is not a valid debug level", rawLevel);
|
||||
return;
|
||||
}
|
||||
|
||||
if (newLevel < 0 || newLevel > Util.MAX_THREADPOOL_LEVEL)
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("{0} is outside the valid debug level range of 0.." + Util.MAX_THREADPOOL_LEVEL, newLevel);
|
||||
return;
|
||||
}
|
||||
|
||||
Util.LogThreadPool = newLevel;
|
||||
MainConsole.Instance.OutputFormat("LogThreadPool set to {0}", newLevel);
|
||||
}
|
||||
|
||||
private void HandleForceGc(string module, string[] args)
|
||||
{
|
||||
Notice("Manually invoking runtime garbage collection");
|
||||
|
||||
@@ -41,323 +41,7 @@ namespace OpenSim.Framework.Servers.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class OSHttpTests : OpenSimTestCase
|
||||
{
|
||||
// we need an IHttpClientContext for our tests
|
||||
public class TestHttpClientContext: IHttpClientContext
|
||||
{
|
||||
private bool _secured;
|
||||
public bool IsSecured
|
||||
{
|
||||
get { return _secured; }
|
||||
}
|
||||
public bool Secured
|
||||
{
|
||||
get { return _secured; }
|
||||
}
|
||||
|
||||
public TestHttpClientContext(bool secured)
|
||||
{
|
||||
_secured = secured;
|
||||
}
|
||||
|
||||
public void Disconnect(SocketError error) {}
|
||||
public void Respond(string httpVersion, HttpStatusCode statusCode, string reason, string body) {}
|
||||
public void Respond(string httpVersion, HttpStatusCode statusCode, string reason) {}
|
||||
public void Respond(string body) {}
|
||||
public void Send(byte[] buffer) {}
|
||||
public void Send(byte[] buffer, int offset, int size) {}
|
||||
public void Respond(string httpVersion, HttpStatusCode statusCode, string reason, string body, string contentType) {}
|
||||
public void Close() { }
|
||||
public bool EndWhenDone { get { return false;} set { return;}}
|
||||
|
||||
public HTTPNetworkContext GiveMeTheNetworkStreamIKnowWhatImDoing()
|
||||
{
|
||||
return new HTTPNetworkContext();
|
||||
}
|
||||
|
||||
public event EventHandler<DisconnectedEventArgs> Disconnected = delegate { };
|
||||
/// <summary>
|
||||
/// A request have been received in the context.
|
||||
/// </summary>
|
||||
public event EventHandler<RequestEventArgs> RequestReceived = delegate { };
|
||||
|
||||
}
|
||||
|
||||
public class TestHttpRequest: IHttpRequest
|
||||
{
|
||||
private string _uriPath;
|
||||
public bool BodyIsComplete
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
public string[] AcceptTypes
|
||||
{
|
||||
get {return _acceptTypes; }
|
||||
}
|
||||
private string[] _acceptTypes;
|
||||
public Stream Body
|
||||
{
|
||||
get { return _body; }
|
||||
set { _body = value;}
|
||||
}
|
||||
private Stream _body;
|
||||
public ConnectionType Connection
|
||||
{
|
||||
get { return _connection; }
|
||||
set { _connection = value; }
|
||||
}
|
||||
private ConnectionType _connection;
|
||||
public int ContentLength
|
||||
{
|
||||
get { return _contentLength; }
|
||||
set { _contentLength = value; }
|
||||
}
|
||||
private int _contentLength;
|
||||
public NameValueCollection Headers
|
||||
{
|
||||
get { return _headers; }
|
||||
}
|
||||
private NameValueCollection _headers = new NameValueCollection();
|
||||
public string HttpVersion
|
||||
{
|
||||
get { return _httpVersion; }
|
||||
set { _httpVersion = value; }
|
||||
}
|
||||
private string _httpVersion = null;
|
||||
public string Method
|
||||
{
|
||||
get { return _method; }
|
||||
set { _method = value; }
|
||||
}
|
||||
private string _method = null;
|
||||
public HttpInput QueryString
|
||||
{
|
||||
get { return _queryString; }
|
||||
}
|
||||
private HttpInput _queryString = null;
|
||||
public Uri Uri
|
||||
{
|
||||
get { return _uri; }
|
||||
set { _uri = value; }
|
||||
}
|
||||
private Uri _uri = null;
|
||||
public string[] UriParts
|
||||
{
|
||||
get { return _uri.Segments; }
|
||||
}
|
||||
public HttpParam Param
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
public HttpForm Form
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
public bool IsAjax
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
public RequestCookies Cookies
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public TestHttpRequest() {}
|
||||
|
||||
public TestHttpRequest(string contentEncoding, string contentType, string userAgent,
|
||||
string remoteAddr, string remotePort, string[] acceptTypes,
|
||||
ConnectionType connectionType, int contentLength, Uri uri)
|
||||
{
|
||||
_headers["content-encoding"] = contentEncoding;
|
||||
_headers["content-type"] = contentType;
|
||||
_headers["user-agent"] = userAgent;
|
||||
_headers["remote_addr"] = remoteAddr;
|
||||
_headers["remote_port"] = remotePort;
|
||||
|
||||
_acceptTypes = acceptTypes;
|
||||
_connection = connectionType;
|
||||
_contentLength = contentLength;
|
||||
_uri = uri;
|
||||
}
|
||||
|
||||
public void DecodeBody(FormDecoderProvider providers) {}
|
||||
public void SetCookies(RequestCookies cookies) {}
|
||||
public void AddHeader(string name, string value)
|
||||
{
|
||||
_headers.Add(name, value);
|
||||
}
|
||||
public int AddToBody(byte[] bytes, int offset, int length)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
public void Clear() {}
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
TestHttpRequest clone = new TestHttpRequest();
|
||||
clone._acceptTypes = _acceptTypes;
|
||||
clone._connection = _connection;
|
||||
clone._contentLength = _contentLength;
|
||||
clone._uri = _uri;
|
||||
clone._headers = new NameValueCollection(_headers);
|
||||
|
||||
return clone;
|
||||
}
|
||||
public IHttpResponse CreateResponse(IHttpClientContext context)
|
||||
{
|
||||
return new HttpResponse(context, this);
|
||||
}
|
||||
/// <summary>
|
||||
/// Path and query (will be merged with the host header) and put in Uri
|
||||
/// </summary>
|
||||
/// <see cref="Uri"/>
|
||||
public string UriPath
|
||||
{
|
||||
get { return _uriPath; }
|
||||
set
|
||||
{
|
||||
_uriPath = value;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class TestHttpResponse: IHttpResponse
|
||||
{
|
||||
public Stream Body
|
||||
{
|
||||
get { return _body; }
|
||||
|
||||
set { _body = value; }
|
||||
}
|
||||
private Stream _body;
|
||||
|
||||
public string ProtocolVersion
|
||||
{
|
||||
get { return _protocolVersion; }
|
||||
set { _protocolVersion = value; }
|
||||
}
|
||||
private string _protocolVersion;
|
||||
|
||||
public bool Chunked
|
||||
{
|
||||
get { return _chunked; }
|
||||
|
||||
set { _chunked = value; }
|
||||
}
|
||||
private bool _chunked;
|
||||
|
||||
public ConnectionType Connection
|
||||
{
|
||||
get { return _connection; }
|
||||
|
||||
set { _connection = value; }
|
||||
}
|
||||
private ConnectionType _connection;
|
||||
|
||||
public Encoding Encoding
|
||||
{
|
||||
get { return _encoding; }
|
||||
|
||||
set { _encoding = value; }
|
||||
}
|
||||
private Encoding _encoding;
|
||||
|
||||
public int KeepAlive
|
||||
{
|
||||
get { return _keepAlive; }
|
||||
|
||||
set { _keepAlive = value; }
|
||||
}
|
||||
private int _keepAlive;
|
||||
|
||||
public HttpStatusCode Status
|
||||
{
|
||||
get { return _status; }
|
||||
|
||||
set { _status = value; }
|
||||
}
|
||||
private HttpStatusCode _status;
|
||||
|
||||
public string Reason
|
||||
{
|
||||
get { return _reason; }
|
||||
|
||||
set { _reason = value; }
|
||||
}
|
||||
private string _reason;
|
||||
|
||||
public long ContentLength
|
||||
{
|
||||
get { return _contentLength; }
|
||||
|
||||
set { _contentLength = value; }
|
||||
}
|
||||
private long _contentLength;
|
||||
|
||||
public string ContentType
|
||||
{
|
||||
get { return _contentType; }
|
||||
|
||||
set { _contentType = value; }
|
||||
}
|
||||
private string _contentType;
|
||||
|
||||
public bool HeadersSent
|
||||
{
|
||||
get { return _headersSent; }
|
||||
}
|
||||
private bool _headersSent;
|
||||
|
||||
public bool Sent
|
||||
{
|
||||
get { return _sent; }
|
||||
}
|
||||
private bool _sent;
|
||||
|
||||
public ResponseCookies Cookies
|
||||
{
|
||||
get { return _cookies; }
|
||||
}
|
||||
private ResponseCookies _cookies = null;
|
||||
|
||||
public TestHttpResponse()
|
||||
{
|
||||
_headersSent = false;
|
||||
_sent = false;
|
||||
}
|
||||
|
||||
public void AddHeader(string name, string value) {}
|
||||
public void Send()
|
||||
{
|
||||
if (!_headersSent) SendHeaders();
|
||||
if (_sent) throw new InvalidOperationException("stuff already sent");
|
||||
_sent = true;
|
||||
}
|
||||
|
||||
public void SendBody(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (!_headersSent) SendHeaders();
|
||||
_sent = true;
|
||||
}
|
||||
public void SendBody(byte[] buffer)
|
||||
{
|
||||
if (!_headersSent) SendHeaders();
|
||||
_sent = true;
|
||||
}
|
||||
|
||||
public void SendHeaders()
|
||||
{
|
||||
if (_headersSent) throw new InvalidOperationException("headers already sent");
|
||||
_headersSent = true;
|
||||
}
|
||||
|
||||
public void Redirect(Uri uri) {}
|
||||
public void Redirect(string url) {}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
public OSHttpRequest req0;
|
||||
public OSHttpRequest req1;
|
||||
|
||||
@@ -429,4 +113,4 @@ namespace OpenSim.Framework.Servers.Tests
|
||||
Assert.That(rsp0.ContentType, Is.EqualTo("text/xml"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Reflection;
|
||||
|
||||
using Nini.Config;
|
||||
using log4net;
|
||||
|
||||
namespace OpenSim.Framework.ServiceAuth
|
||||
{
|
||||
public class BasicHttpAuthentication : IServiceAuth
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private string m_Username, m_Password;
|
||||
private string m_CredentialsB64;
|
||||
|
||||
private string remove_me;
|
||||
|
||||
public string Credentials
|
||||
{
|
||||
get { return m_CredentialsB64; }
|
||||
}
|
||||
|
||||
public BasicHttpAuthentication(IConfigSource config, string section)
|
||||
{
|
||||
remove_me = section;
|
||||
m_Username = Util.GetConfigVarFromSections<string>(config, "HttpAuthUsername", new string[] { "Network", section }, string.Empty);
|
||||
m_Password = Util.GetConfigVarFromSections<string>(config, "HttpAuthPassword", new string[] { "Network", section }, string.Empty);
|
||||
string str = m_Username + ":" + m_Password;
|
||||
byte[] encData_byte = Util.UTF8.GetBytes(str);
|
||||
|
||||
m_CredentialsB64 = Convert.ToBase64String(encData_byte);
|
||||
m_log.DebugFormat("[HTTP BASIC AUTH]: {0} {1} [{2}]", m_Username, m_Password, section);
|
||||
}
|
||||
|
||||
public void AddAuthorization(NameValueCollection headers)
|
||||
{
|
||||
//m_log.DebugFormat("[HTTP BASIC AUTH]: Adding authorization for {0}", remove_me);
|
||||
headers["Authorization"] = "Basic " + m_CredentialsB64;
|
||||
}
|
||||
|
||||
public bool Authenticate(string data)
|
||||
{
|
||||
string recovered = Util.Base64ToString(data);
|
||||
if (!String.IsNullOrEmpty(recovered))
|
||||
{
|
||||
string[] parts = recovered.Split(new char[] { ':' });
|
||||
if (parts.Length >= 2)
|
||||
{
|
||||
return m_Username.Equals(parts[0]) && m_Password.Equals(parts[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Authenticate(NameValueCollection requestHeaders, AddHeaderDelegate d)
|
||||
{
|
||||
//m_log.DebugFormat("[HTTP BASIC AUTH]: Authenticate in {0}", remove_me);
|
||||
if (requestHeaders != null)
|
||||
{
|
||||
string value = requestHeaders.Get("Authorization");
|
||||
if (value != null)
|
||||
{
|
||||
value = value.Trim();
|
||||
if (value.StartsWith("Basic "))
|
||||
{
|
||||
value = value.Replace("Basic ", string.Empty);
|
||||
if (Authenticate(value))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
d("WWW-Authenticate", "Basic realm = \"Asset Server\"");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace OpenSim.Framework.ServiceAuth
|
||||
{
|
||||
public delegate void AddHeaderDelegate(string key, string value);
|
||||
|
||||
public interface IServiceAuth
|
||||
{
|
||||
bool Authenticate(string data);
|
||||
bool Authenticate(NameValueCollection headers, AddHeaderDelegate d);
|
||||
void AddAuthorization(NameValueCollection headers);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Nini.Config;
|
||||
|
||||
namespace OpenSim.Framework.ServiceAuth
|
||||
{
|
||||
public class ServiceAuth
|
||||
{
|
||||
public static IServiceAuth Create(IConfigSource config, string section)
|
||||
{
|
||||
string authType = Util.GetConfigVarFromSections<string>(config, "AuthType", new string[] { "Network", section }, "None");
|
||||
|
||||
switch (authType)
|
||||
{
|
||||
case "BasicHttpAuthentication":
|
||||
return new BasicHttpAuthentication(config, section);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,8 +50,9 @@ namespace OpenSim.Framework
|
||||
// Someday terrain will have caves
|
||||
public abstract float this[int x, int y, int z] { get; set; }
|
||||
|
||||
public bool IsTainted { get; protected set; }
|
||||
public abstract bool IsTaintedAt(int xx, int yy);
|
||||
public abstract bool IsTaintedAt(int xx, int yy, bool clearOnTest);
|
||||
public abstract void TaintAllTerrain();
|
||||
public abstract void ClearTaint();
|
||||
|
||||
public abstract void ClearLand();
|
||||
@@ -71,10 +72,11 @@ namespace OpenSim.Framework
|
||||
return new HeightmapTerrainData(pSizeX, pSizeY, pSizeZ, pFormatCode, pBlob);
|
||||
}
|
||||
|
||||
// return a special compressed representation of the heightmap in shorts
|
||||
public abstract short[] GetCompressedMap();
|
||||
// return a special compressed representation of the heightmap in ints
|
||||
public abstract int[] GetCompressedMap();
|
||||
public abstract float CompressionFactor { get; }
|
||||
|
||||
public abstract float[] GetFloatsSerialized();
|
||||
public abstract double[,] GetDoubles();
|
||||
public abstract TerrainData Clone();
|
||||
}
|
||||
@@ -97,7 +99,7 @@ namespace OpenSim.Framework
|
||||
Variable2D = 22,
|
||||
// Terrain is 'int32, int32, int32, int16[]' where the ints are X and Y dimensions
|
||||
// and third int is the 'compression factor'. The heights are compressed as
|
||||
// "short compressedHeight = (short)(height * compressionFactor);"
|
||||
// "int compressedHeight = (int)(height * compressionFactor);"
|
||||
// The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256.
|
||||
Compressed2D = 27,
|
||||
// A revision that is not listed above or any revision greater than this value is 'Legacy256'.
|
||||
@@ -107,8 +109,8 @@ namespace OpenSim.Framework
|
||||
// Version of terrain that is a heightmap.
|
||||
// This should really be 'LLOptimizedHeightmapTerrainData' as it includes knowledge
|
||||
// of 'patches' which are 16x16 terrain areas which can be sent separately to the viewer.
|
||||
// The heighmap is kept as an array of short integers. The integer values are converted to
|
||||
// and from floats by TerrainCompressionFactor. Shorts are used to limit storage used.
|
||||
// The heighmap is kept as an array of integers. The integer values are converted to
|
||||
// and from floats by TerrainCompressionFactor.
|
||||
public class HeightmapTerrainData : TerrainData
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
@@ -119,7 +121,7 @@ namespace OpenSim.Framework
|
||||
{
|
||||
get { return FromCompressedHeight(m_heightmap[x, y]); }
|
||||
set {
|
||||
short newVal = ToCompressedHeight(value);
|
||||
int newVal = ToCompressedHeight(value);
|
||||
if (m_heightmap[x, y] != newVal)
|
||||
{
|
||||
m_heightmap[x, y] = newVal;
|
||||
@@ -138,10 +140,20 @@ namespace OpenSim.Framework
|
||||
// TerrainData.ClearTaint
|
||||
public override void ClearTaint()
|
||||
{
|
||||
IsTainted = false;
|
||||
SetAllTaint(false);
|
||||
}
|
||||
|
||||
// TerrainData.TaintAllTerrain
|
||||
public override void TaintAllTerrain()
|
||||
{
|
||||
SetAllTaint(true);
|
||||
}
|
||||
|
||||
private void SetAllTaint(bool setting)
|
||||
{
|
||||
for (int ii = 0; ii < m_taint.GetLength(0); ii++)
|
||||
for (int jj = 0; jj < m_taint.GetLength(1); jj++)
|
||||
m_taint[ii, jj] = false;
|
||||
m_taint[ii, jj] = setting;
|
||||
}
|
||||
|
||||
// TerrainData.ClearLand
|
||||
@@ -152,21 +164,31 @@ namespace OpenSim.Framework
|
||||
// TerrainData.ClearLand(float)
|
||||
public override void ClearLand(float pHeight)
|
||||
{
|
||||
short flatHeight = ToCompressedHeight(pHeight);
|
||||
int flatHeight = ToCompressedHeight(pHeight);
|
||||
for (int xx = 0; xx < SizeX; xx++)
|
||||
for (int yy = 0; yy < SizeY; yy++)
|
||||
m_heightmap[xx, yy] = flatHeight;
|
||||
}
|
||||
|
||||
public override bool IsTaintedAt(int xx, int yy)
|
||||
// Return 'true' of the patch that contains these region coordinates has been modified.
|
||||
// Note that checking the taint clears it.
|
||||
// There is existing code that relies on this feature.
|
||||
public override bool IsTaintedAt(int xx, int yy, bool clearOnTest)
|
||||
{
|
||||
int tx = xx / Constants.TerrainPatchSize;
|
||||
int ty = yy / Constants.TerrainPatchSize;
|
||||
bool ret = m_taint[tx, ty];
|
||||
m_taint[tx, ty] = false;
|
||||
if (ret && clearOnTest)
|
||||
m_taint[tx, ty] = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Old form that clears the taint flag when we check it.
|
||||
public override bool IsTaintedAt(int xx, int yy)
|
||||
{
|
||||
return IsTaintedAt(xx, yy, true /* clearOnTest */);
|
||||
}
|
||||
|
||||
// TerrainData.GetDatabaseBlob
|
||||
// The user wants something to store in the database.
|
||||
public override bool GetDatabaseBlob(out int DBRevisionCode, out Array blob)
|
||||
@@ -192,9 +214,9 @@ namespace OpenSim.Framework
|
||||
public override float CompressionFactor { get { return m_compressionFactor; } }
|
||||
|
||||
// TerrainData.GetCompressedMap
|
||||
public override short[] GetCompressedMap()
|
||||
public override int[] GetCompressedMap()
|
||||
{
|
||||
short[] newMap = new short[SizeX * SizeY];
|
||||
int[] newMap = new int[SizeX * SizeY];
|
||||
|
||||
int ind = 0;
|
||||
for (int xx = 0; xx < SizeX; xx++)
|
||||
@@ -208,10 +230,29 @@ namespace OpenSim.Framework
|
||||
public override TerrainData Clone()
|
||||
{
|
||||
HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ);
|
||||
ret.m_heightmap = (short[,])this.m_heightmap.Clone();
|
||||
ret.m_heightmap = (int[,])this.m_heightmap.Clone();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// TerrainData.GetFloatsSerialized
|
||||
// This one dimensional version is ordered so height = map[y*sizeX+x];
|
||||
// DEPRECATED: don't use this function as it does not retain the dimensions of the terrain
|
||||
// and the caller will probably do the wrong thing if the terrain is not the legacy 256x256.
|
||||
public override float[] GetFloatsSerialized()
|
||||
{
|
||||
int points = SizeX * SizeY;
|
||||
float[] heights = new float[points];
|
||||
|
||||
int idx = 0;
|
||||
for (int jj = 0; jj < SizeY; jj++)
|
||||
for (int ii = 0; ii < SizeX; ii++)
|
||||
{
|
||||
heights[idx++] = FromCompressedHeight(m_heightmap[ii, jj]);
|
||||
}
|
||||
|
||||
return heights;
|
||||
}
|
||||
|
||||
// TerrainData.GetDoubles
|
||||
public override double[,] GetDoubles()
|
||||
{
|
||||
@@ -226,19 +267,19 @@ namespace OpenSim.Framework
|
||||
|
||||
// =============================================================
|
||||
|
||||
private short[,] m_heightmap;
|
||||
private int[,] m_heightmap;
|
||||
// Remember subregions of the heightmap that has changed.
|
||||
private bool[,] m_taint;
|
||||
|
||||
// To save space (especially for large regions), keep the height as a short integer
|
||||
// that is coded as the float height times the compression factor (usually '100'
|
||||
// to make for two decimal points).
|
||||
public short ToCompressedHeight(double pHeight)
|
||||
public int ToCompressedHeight(double pHeight)
|
||||
{
|
||||
return (short)(pHeight * CompressionFactor);
|
||||
return (int)(pHeight * CompressionFactor);
|
||||
}
|
||||
|
||||
public float FromCompressedHeight(short pHeight)
|
||||
public float FromCompressedHeight(int pHeight)
|
||||
{
|
||||
return ((float)pHeight) / CompressionFactor;
|
||||
}
|
||||
@@ -252,7 +293,7 @@ namespace OpenSim.Framework
|
||||
SizeZ = (int)Constants.RegionHeight;
|
||||
m_compressionFactor = 100.0f;
|
||||
|
||||
m_heightmap = new short[SizeX, SizeY];
|
||||
m_heightmap = new int[SizeX, SizeY];
|
||||
for (int ii = 0; ii < SizeX; ii++)
|
||||
{
|
||||
for (int jj = 0; jj < SizeY; jj++)
|
||||
@@ -274,14 +315,14 @@ namespace OpenSim.Framework
|
||||
SizeY = pY;
|
||||
SizeZ = pZ;
|
||||
m_compressionFactor = 100.0f;
|
||||
m_heightmap = new short[SizeX, SizeY];
|
||||
m_heightmap = new int[SizeX, SizeY];
|
||||
m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize];
|
||||
// m_log.DebugFormat("{0} new by dimensions. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ);
|
||||
ClearTaint();
|
||||
ClearLand(0f);
|
||||
}
|
||||
|
||||
public HeightmapTerrainData(short[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ)
|
||||
public HeightmapTerrainData(int[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ)
|
||||
{
|
||||
m_compressionFactor = pCompressionFactor;
|
||||
int ind = 0;
|
||||
|
||||
@@ -299,7 +299,7 @@ namespace OpenSim.Framework.Tests
|
||||
uint z1 = 22;
|
||||
ulong regionHandle2;
|
||||
uint x2, y2, z2;
|
||||
UUID fakeParcelID1, fakeParcelID2, uuid;
|
||||
UUID fakeParcelID1, uuid;
|
||||
|
||||
ulong bigInt64 = Util.BytesToUInt64Big(hexBytes8);
|
||||
Assert.AreEqual(var64Bit, bigInt64,
|
||||
|
||||
@@ -1,230 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Security;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Used for requests to untrusted endpoints that may potentially be
|
||||
/// malicious
|
||||
/// </summary>
|
||||
public static class UntrustedHttpWebRequest
|
||||
{
|
||||
/// <summary>Setting this to true will allow HTTP connections to localhost</summary>
|
||||
private const bool DEBUG = true;
|
||||
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(
|
||||
System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private static readonly ICollection<string> allowableSchemes = new List<string> { "http", "https" };
|
||||
|
||||
/// <summary>
|
||||
/// Creates an HttpWebRequest that is hardened against malicious
|
||||
/// endpoints after ensuring the given Uri is safe to retrieve
|
||||
/// </summary>
|
||||
/// <param name="uri">Web location to request</param>
|
||||
/// <returns>A hardened HttpWebRequest if the uri was determined to be safe</returns>
|
||||
/// <exception cref="ArgumentNullException">If uri is null</exception>
|
||||
/// <exception cref="ArgumentException">If uri is unsafe</exception>
|
||||
public static HttpWebRequest Create(Uri uri)
|
||||
{
|
||||
return Create(uri, DEBUG, 1000 * 5, 1000 * 20, 10);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an HttpWebRequest that is hardened against malicious
|
||||
/// endpoints after ensuring the given Uri is safe to retrieve
|
||||
/// </summary>
|
||||
/// <param name="uri">Web location to request</param>
|
||||
/// <param name="allowLoopback">True to allow connections to localhost, otherwise false</param>
|
||||
/// <param name="readWriteTimeoutMS">Read write timeout, in milliseconds</param>
|
||||
/// <param name="timeoutMS">Connection timeout, in milliseconds</param>
|
||||
/// <param name="maximumRedirects">Maximum number of allowed redirects</param>
|
||||
/// <returns>A hardened HttpWebRequest if the uri was determined to be safe</returns>
|
||||
/// <exception cref="ArgumentNullException">If uri is null</exception>
|
||||
/// <exception cref="ArgumentException">If uri is unsafe</exception>
|
||||
public static HttpWebRequest Create(Uri uri, bool allowLoopback, int readWriteTimeoutMS, int timeoutMS, int maximumRedirects)
|
||||
{
|
||||
if (uri == null)
|
||||
throw new ArgumentNullException("uri");
|
||||
|
||||
if (!IsUriAllowable(uri, allowLoopback))
|
||||
throw new ArgumentException("Uri " + uri + " was rejected");
|
||||
|
||||
HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(uri);
|
||||
httpWebRequest.MaximumAutomaticRedirections = maximumRedirects;
|
||||
httpWebRequest.ReadWriteTimeout = readWriteTimeoutMS;
|
||||
httpWebRequest.Timeout = timeoutMS;
|
||||
httpWebRequest.KeepAlive = false;
|
||||
|
||||
return httpWebRequest;
|
||||
}
|
||||
|
||||
public static string PostToUntrustedUrl(Uri url, string data)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] requestData = System.Text.Encoding.UTF8.GetBytes(data);
|
||||
|
||||
HttpWebRequest request = Create(url);
|
||||
request.Method = "POST";
|
||||
request.ContentLength = requestData.Length;
|
||||
request.ContentType = "application/x-www-form-urlencoded";
|
||||
|
||||
using (Stream requestStream = request.GetRequestStream())
|
||||
requestStream.Write(requestData, 0, requestData.Length);
|
||||
|
||||
using (WebResponse response = request.GetResponse())
|
||||
{
|
||||
using (Stream responseStream = response.GetResponseStream())
|
||||
return responseStream.GetStreamString();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Warn("POST to untrusted URL " + url + " failed: " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetUntrustedUrl(Uri url)
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpWebRequest request = Create(url);
|
||||
|
||||
using (WebResponse response = request.GetResponse())
|
||||
{
|
||||
using (Stream responseStream = response.GetResponseStream())
|
||||
return responseStream.GetStreamString();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Warn("GET from untrusted URL " + url + " failed: " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a URI is allowed based on scheme and host name.
|
||||
/// No requireSSL check is done here
|
||||
/// </summary>
|
||||
/// <param name="allowLoopback">True to allow loopback addresses to be used</param>
|
||||
/// <param name="uri">The URI to test for whether it should be allowed.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if [is URI allowable] [the specified URI]; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
private static bool IsUriAllowable(Uri uri, bool allowLoopback)
|
||||
{
|
||||
if (!allowableSchemes.Contains(uri.Scheme))
|
||||
{
|
||||
m_log.WarnFormat("Rejecting URL {0} because it uses a disallowed scheme.", uri);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to interpret the hostname as an IP address so we can test for internal
|
||||
// IP address ranges. Note that IP addresses can appear in many forms
|
||||
// (e.g. http://127.0.0.1, http://2130706433, http://0x0100007f, http://::1
|
||||
// So we convert them to a canonical IPAddress instance, and test for all
|
||||
// non-routable IP ranges: 10.*.*.*, 127.*.*.*, ::1
|
||||
// Note that Uri.IsLoopback is very unreliable, not catching many of these variants.
|
||||
IPAddress hostIPAddress;
|
||||
if (IPAddress.TryParse(uri.DnsSafeHost, out hostIPAddress))
|
||||
{
|
||||
byte[] addressBytes = hostIPAddress.GetAddressBytes();
|
||||
|
||||
// The host is actually an IP address.
|
||||
switch (hostIPAddress.AddressFamily)
|
||||
{
|
||||
case System.Net.Sockets.AddressFamily.InterNetwork:
|
||||
if (!allowLoopback && (addressBytes[0] == 127 || addressBytes[0] == 10))
|
||||
{
|
||||
m_log.WarnFormat("Rejecting URL {0} because it is a loopback address.", uri);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case System.Net.Sockets.AddressFamily.InterNetworkV6:
|
||||
if (!allowLoopback && IsIPv6Loopback(hostIPAddress))
|
||||
{
|
||||
m_log.WarnFormat("Rejecting URL {0} because it is a loopback address.", uri);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_log.WarnFormat("Rejecting URL {0} because it does not use an IPv4 or IPv6 address.", uri);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The host is given by name. We require names to contain periods to
|
||||
// help make sure it's not an internal address.
|
||||
if (!allowLoopback && !uri.Host.Contains("."))
|
||||
{
|
||||
m_log.WarnFormat("Rejecting URL {0} because it does not contain a period in the host name.", uri);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether an IP address is the IPv6 equivalent of "localhost/127.0.0.1".
|
||||
/// </summary>
|
||||
/// <param name="ip">The ip address to check.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this is a loopback IP address; <c>false</c> otherwise.
|
||||
/// </returns>
|
||||
private static bool IsIPv6Loopback(IPAddress ip)
|
||||
{
|
||||
if (ip == null)
|
||||
throw new ArgumentNullException("ip");
|
||||
|
||||
byte[] addressBytes = ip.GetAddressBytes();
|
||||
for (int i = 0; i < addressBytes.Length - 1; i++)
|
||||
{
|
||||
if (addressBytes[i] != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (addressBytes[addressBytes.Length - 1] != 1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+710
-118
@@ -51,6 +51,9 @@ using Nwc.XmlRpc;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using Amib.Threading;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Specialized;
|
||||
using System.Web;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
@@ -67,7 +70,7 @@ namespace OpenSim.Framework
|
||||
// All does not contain Export, which is special and must be
|
||||
// explicitly given
|
||||
All = (1 << 13) | (1 << 14) | (1 << 15) | (1 << 19)
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The method used by Util.FireAndForget for asynchronously firing events
|
||||
@@ -116,6 +119,24 @@ namespace OpenSim.Framework
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
/// <summary>
|
||||
/// Log-level for the thread pool:
|
||||
/// 0 = no logging
|
||||
/// 1 = only first line of stack trace; don't log common threads
|
||||
/// 2 = full stack trace; don't log common threads
|
||||
/// 3 = full stack trace, including common threads
|
||||
/// </summary>
|
||||
public static int LogThreadPool { get; set; }
|
||||
public static bool LogOverloads { get; set; }
|
||||
|
||||
public static readonly int MAX_THREADPOOL_LEVEL = 3;
|
||||
|
||||
static Util()
|
||||
{
|
||||
LogThreadPool = 0;
|
||||
LogOverloads = true;
|
||||
}
|
||||
|
||||
private static uint nextXferID = 5000;
|
||||
private static Random randomClass = new Random();
|
||||
|
||||
@@ -129,6 +150,9 @@ namespace OpenSim.Framework
|
||||
/// </summary>
|
||||
private static SmartThreadPool m_ThreadPool;
|
||||
|
||||
// Watchdog timer that aborts threads that have timed-out
|
||||
private static Timer m_threadPoolWatchdog;
|
||||
|
||||
// Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC.
|
||||
public static readonly DateTime UnixEpoch =
|
||||
DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime();
|
||||
@@ -845,6 +869,54 @@ namespace OpenSim.Framework
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a foreign asset ID.
|
||||
/// </summary>
|
||||
/// <param name="id">A possibly-foreign asset ID: http://grid.example.com:8002/00000000-0000-0000-0000-000000000000 </param>
|
||||
/// <param name="url">The URL: http://grid.example.com:8002</param>
|
||||
/// <param name="assetID">The asset ID: 00000000-0000-0000-0000-000000000000. Returned even if 'id' isn't foreign.</param>
|
||||
/// <returns>True: this is a foreign asset ID; False: it isn't</returns>
|
||||
public static bool ParseForeignAssetID(string id, out string url, out string assetID)
|
||||
{
|
||||
url = String.Empty;
|
||||
assetID = String.Empty;
|
||||
|
||||
UUID uuid;
|
||||
if (UUID.TryParse(id, out uuid))
|
||||
{
|
||||
assetID = uuid.ToString();
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((id.Length == 0) || (id[0] != 'h' && id[0] != 'H'))
|
||||
return false;
|
||||
|
||||
Uri assetUri;
|
||||
if (!Uri.TryCreate(id, UriKind.Absolute, out assetUri) || assetUri.Scheme != Uri.UriSchemeHttp)
|
||||
return false;
|
||||
|
||||
// Simian
|
||||
if (assetUri.Query != string.Empty)
|
||||
{
|
||||
NameValueCollection qscoll = HttpUtility.ParseQueryString(assetUri.Query);
|
||||
assetID = qscoll["id"];
|
||||
if (assetID != null)
|
||||
url = id.Replace(assetID, ""); // Malformed again, as simian expects
|
||||
else
|
||||
url = id; // !!! best effort
|
||||
}
|
||||
else // robust
|
||||
{
|
||||
url = "http://" + assetUri.Authority;
|
||||
assetID = assetUri.LocalPath.Trim(new char[] { '/' });
|
||||
}
|
||||
|
||||
if (!UUID.TryParse(assetID, out uuid))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all invalid path chars (OS dependent)
|
||||
/// </summary>
|
||||
@@ -946,11 +1018,12 @@ namespace OpenSim.Framework
|
||||
}
|
||||
|
||||
#region Nini (config) related Methods
|
||||
|
||||
public static IConfigSource ConvertDataRowToXMLConfig(DataRow row, string fileName)
|
||||
{
|
||||
if (!File.Exists(fileName))
|
||||
{
|
||||
//create new file
|
||||
// create new file
|
||||
}
|
||||
XmlConfigSource config = new XmlConfigSource(fileName);
|
||||
AddDataRowToConfig(config, row);
|
||||
@@ -968,25 +1041,6 @@ namespace OpenSim.Framework
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetConfigVarWithDefaultSection(IConfigSource config, string varname, string section)
|
||||
{
|
||||
// First, check the Startup section, the default section
|
||||
IConfig cnf = config.Configs["Startup"];
|
||||
if (cnf == null)
|
||||
return string.Empty;
|
||||
string val = cnf.GetString(varname, string.Empty);
|
||||
|
||||
// Then check for an overwrite of the default in the given section
|
||||
if (!string.IsNullOrEmpty(section))
|
||||
{
|
||||
cnf = config.Configs[section];
|
||||
if (cnf != null)
|
||||
val = cnf.GetString(varname, val);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of a configuration variable by looking into
|
||||
/// multiple sections in order. The latter sections overwrite
|
||||
@@ -1039,6 +1093,91 @@ namespace OpenSim.Framework
|
||||
return (T)val;
|
||||
}
|
||||
|
||||
public static void MergeEnvironmentToConfig(IConfigSource ConfigSource)
|
||||
{
|
||||
IConfig enVars = ConfigSource.Configs["Environment"];
|
||||
// if section does not exist then user isn't expecting them, so don't bother.
|
||||
if( enVars != null )
|
||||
{
|
||||
// load the values from the environment
|
||||
EnvConfigSource envConfigSource = new EnvConfigSource();
|
||||
// add the requested keys
|
||||
string[] env_keys = enVars.GetKeys();
|
||||
foreach ( string key in env_keys )
|
||||
{
|
||||
envConfigSource.AddEnv(key, string.Empty);
|
||||
}
|
||||
// load the values from environment
|
||||
envConfigSource.LoadEnv();
|
||||
// add them in to the master
|
||||
ConfigSource.Merge(envConfigSource);
|
||||
ConfigSource.ExpandKeyValues();
|
||||
}
|
||||
}
|
||||
|
||||
public static T ReadSettingsFromIniFile<T>(IConfig config, T settingsClass)
|
||||
{
|
||||
Type settingsType = settingsClass.GetType();
|
||||
|
||||
FieldInfo[] fieldInfos = settingsType.GetFields();
|
||||
foreach (FieldInfo fieldInfo in fieldInfos)
|
||||
{
|
||||
if (!fieldInfo.IsStatic)
|
||||
{
|
||||
if (fieldInfo.FieldType == typeof(System.String))
|
||||
{
|
||||
fieldInfo.SetValue(settingsClass, config.Get(fieldInfo.Name, (string)fieldInfo.GetValue(settingsClass)));
|
||||
}
|
||||
else if (fieldInfo.FieldType == typeof(System.Boolean))
|
||||
{
|
||||
fieldInfo.SetValue(settingsClass, config.GetBoolean(fieldInfo.Name, (bool)fieldInfo.GetValue(settingsClass)));
|
||||
}
|
||||
else if (fieldInfo.FieldType == typeof(System.Int32))
|
||||
{
|
||||
fieldInfo.SetValue(settingsClass, config.GetInt(fieldInfo.Name, (int)fieldInfo.GetValue(settingsClass)));
|
||||
}
|
||||
else if (fieldInfo.FieldType == typeof(System.Single))
|
||||
{
|
||||
fieldInfo.SetValue(settingsClass, config.GetFloat(fieldInfo.Name, (float)fieldInfo.GetValue(settingsClass)));
|
||||
}
|
||||
else if (fieldInfo.FieldType == typeof(System.UInt32))
|
||||
{
|
||||
fieldInfo.SetValue(settingsClass, Convert.ToUInt32(config.Get(fieldInfo.Name, ((uint)fieldInfo.GetValue(settingsClass)).ToString())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PropertyInfo[] propertyInfos = settingsType.GetProperties();
|
||||
foreach (PropertyInfo propInfo in propertyInfos)
|
||||
{
|
||||
if ((propInfo.CanRead) && (propInfo.CanWrite))
|
||||
{
|
||||
if (propInfo.PropertyType == typeof(System.String))
|
||||
{
|
||||
propInfo.SetValue(settingsClass, config.Get(propInfo.Name, (string)propInfo.GetValue(settingsClass, null)), null);
|
||||
}
|
||||
else if (propInfo.PropertyType == typeof(System.Boolean))
|
||||
{
|
||||
propInfo.SetValue(settingsClass, config.GetBoolean(propInfo.Name, (bool)propInfo.GetValue(settingsClass, null)), null);
|
||||
}
|
||||
else if (propInfo.PropertyType == typeof(System.Int32))
|
||||
{
|
||||
propInfo.SetValue(settingsClass, config.GetInt(propInfo.Name, (int)propInfo.GetValue(settingsClass, null)), null);
|
||||
}
|
||||
else if (propInfo.PropertyType == typeof(System.Single))
|
||||
{
|
||||
propInfo.SetValue(settingsClass, config.GetFloat(propInfo.Name, (float)propInfo.GetValue(settingsClass, null)), null);
|
||||
}
|
||||
if (propInfo.PropertyType == typeof(System.UInt32))
|
||||
{
|
||||
propInfo.SetValue(settingsClass, Convert.ToUInt32(config.Get(propInfo.Name, ((uint)propInfo.GetValue(settingsClass, null)).ToString())), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return settingsClass;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static float Clip(float x, float min, float max)
|
||||
@@ -1411,69 +1550,6 @@ namespace OpenSim.Framework
|
||||
return displayConnectionString;
|
||||
}
|
||||
|
||||
public static T ReadSettingsFromIniFile<T>(IConfig config, T settingsClass)
|
||||
{
|
||||
Type settingsType = settingsClass.GetType();
|
||||
|
||||
FieldInfo[] fieldInfos = settingsType.GetFields();
|
||||
foreach (FieldInfo fieldInfo in fieldInfos)
|
||||
{
|
||||
if (!fieldInfo.IsStatic)
|
||||
{
|
||||
if (fieldInfo.FieldType == typeof(System.String))
|
||||
{
|
||||
fieldInfo.SetValue(settingsClass, config.Get(fieldInfo.Name, (string)fieldInfo.GetValue(settingsClass)));
|
||||
}
|
||||
else if (fieldInfo.FieldType == typeof(System.Boolean))
|
||||
{
|
||||
fieldInfo.SetValue(settingsClass, config.GetBoolean(fieldInfo.Name, (bool)fieldInfo.GetValue(settingsClass)));
|
||||
}
|
||||
else if (fieldInfo.FieldType == typeof(System.Int32))
|
||||
{
|
||||
fieldInfo.SetValue(settingsClass, config.GetInt(fieldInfo.Name, (int)fieldInfo.GetValue(settingsClass)));
|
||||
}
|
||||
else if (fieldInfo.FieldType == typeof(System.Single))
|
||||
{
|
||||
fieldInfo.SetValue(settingsClass, config.GetFloat(fieldInfo.Name, (float)fieldInfo.GetValue(settingsClass)));
|
||||
}
|
||||
else if (fieldInfo.FieldType == typeof(System.UInt32))
|
||||
{
|
||||
fieldInfo.SetValue(settingsClass, Convert.ToUInt32(config.Get(fieldInfo.Name, ((uint)fieldInfo.GetValue(settingsClass)).ToString())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PropertyInfo[] propertyInfos = settingsType.GetProperties();
|
||||
foreach (PropertyInfo propInfo in propertyInfos)
|
||||
{
|
||||
if ((propInfo.CanRead) && (propInfo.CanWrite))
|
||||
{
|
||||
if (propInfo.PropertyType == typeof(System.String))
|
||||
{
|
||||
propInfo.SetValue(settingsClass, config.Get(propInfo.Name, (string)propInfo.GetValue(settingsClass, null)), null);
|
||||
}
|
||||
else if (propInfo.PropertyType == typeof(System.Boolean))
|
||||
{
|
||||
propInfo.SetValue(settingsClass, config.GetBoolean(propInfo.Name, (bool)propInfo.GetValue(settingsClass, null)), null);
|
||||
}
|
||||
else if (propInfo.PropertyType == typeof(System.Int32))
|
||||
{
|
||||
propInfo.SetValue(settingsClass, config.GetInt(propInfo.Name, (int)propInfo.GetValue(settingsClass, null)), null);
|
||||
}
|
||||
else if (propInfo.PropertyType == typeof(System.Single))
|
||||
{
|
||||
propInfo.SetValue(settingsClass, config.GetFloat(propInfo.Name, (float)propInfo.GetValue(settingsClass, null)), null);
|
||||
}
|
||||
if (propInfo.PropertyType == typeof(System.UInt32))
|
||||
{
|
||||
propInfo.SetValue(settingsClass, Convert.ToUInt32(config.Get(propInfo.Name, ((uint)propInfo.GetValue(settingsClass, null)).ToString())), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return settingsClass;
|
||||
}
|
||||
|
||||
public static string Base64ToString(string str)
|
||||
{
|
||||
Decoder utf8Decode = Encoding.UTF8.GetDecoder();
|
||||
@@ -1486,6 +1562,46 @@ namespace OpenSim.Framework
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void BinaryToASCII(char[] chars)
|
||||
{
|
||||
for (int i = 0; i < chars.Length; i++)
|
||||
{
|
||||
char ch = chars[i];
|
||||
if (ch < 32 || ch > 127)
|
||||
chars[i] = '.';
|
||||
}
|
||||
}
|
||||
|
||||
public static string BinaryToASCII(string src)
|
||||
{
|
||||
char[] chars = src.ToCharArray();
|
||||
BinaryToASCII(chars);
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a known number of bytes from a stream.
|
||||
/// Throws EndOfStreamException if the stream doesn't contain enough data.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to read data from</param>
|
||||
/// <param name="data">The array to write bytes into. The array
|
||||
/// will be completely filled from the stream, so an appropriate
|
||||
/// size must be given.</param>
|
||||
public static void ReadStream(Stream stream, byte[] data)
|
||||
{
|
||||
int offset = 0;
|
||||
int remaining = data.Length;
|
||||
|
||||
while (remaining > 0)
|
||||
{
|
||||
int read = stream.Read(data, offset, remaining);
|
||||
if (read <= 0)
|
||||
throw new EndOfStreamException(String.Format("End of stream reached with {0} bytes left to read", remaining));
|
||||
remaining -= read;
|
||||
offset += read;
|
||||
}
|
||||
}
|
||||
|
||||
public static Guid GetHashGuid(string data, string salt)
|
||||
{
|
||||
byte[] hash = ComputeMD5Hash(data + salt);
|
||||
@@ -1745,6 +1861,30 @@ namespace OpenSim.Framework
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pretty format the hashtable contents to a single line.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Used for debugging output.
|
||||
/// </remarks>
|
||||
/// <param name='ht'></param>
|
||||
public static string PrettyFormatToSingleLine(Hashtable ht)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int i = 0;
|
||||
|
||||
foreach (string key in ht.Keys)
|
||||
{
|
||||
sb.AppendFormat("{0}:{1}", key, ht[key]);
|
||||
|
||||
if (++i < ht.Count)
|
||||
sb.AppendFormat(", ");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to trigger an early library load on Windows systems.
|
||||
/// </summary>
|
||||
@@ -1817,7 +1957,7 @@ namespace OpenSim.Framework
|
||||
|
||||
public static void FireAndForget(System.Threading.WaitCallback callback)
|
||||
{
|
||||
FireAndForget(callback, null);
|
||||
FireAndForget(callback, null, null);
|
||||
}
|
||||
|
||||
public static void InitThreadPool(int minThreads, int maxThreads)
|
||||
@@ -1836,6 +1976,7 @@ namespace OpenSim.Framework
|
||||
startInfo.MinWorkerThreads = minThreads;
|
||||
|
||||
m_ThreadPool = new SmartThreadPool(startInfo);
|
||||
m_threadPoolWatchdog = new Timer(ThreadPoolWatchdog, null, 0, 1000);
|
||||
}
|
||||
|
||||
public static int FireAndForgetCount()
|
||||
@@ -1859,10 +2000,129 @@ namespace OpenSim.Framework
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Additional information about threads in the main thread pool. Used to time how long the
|
||||
/// thread has been running, and abort it if it has timed-out.
|
||||
/// </summary>
|
||||
private class ThreadInfo
|
||||
{
|
||||
public long ThreadFuncNum { get; set; }
|
||||
public string StackTrace { get; set; }
|
||||
private string context;
|
||||
public bool LogThread { get; set; }
|
||||
|
||||
public IWorkItemResult WorkItem { get; set; }
|
||||
public Thread Thread { get; set; }
|
||||
public bool Running { get; set; }
|
||||
public bool Aborted { get; set; }
|
||||
private int started;
|
||||
|
||||
public ThreadInfo(long threadFuncNum, string context)
|
||||
{
|
||||
ThreadFuncNum = threadFuncNum;
|
||||
this.context = context;
|
||||
LogThread = true;
|
||||
Thread = null;
|
||||
Running = false;
|
||||
Aborted = false;
|
||||
}
|
||||
|
||||
public void Started()
|
||||
{
|
||||
Thread = Thread.CurrentThread;
|
||||
started = EnvironmentTickCount();
|
||||
Running = true;
|
||||
}
|
||||
|
||||
public void Ended()
|
||||
{
|
||||
Running = false;
|
||||
}
|
||||
|
||||
public int Elapsed()
|
||||
{
|
||||
return EnvironmentTickCountSubtract(started);
|
||||
}
|
||||
|
||||
public void Abort()
|
||||
{
|
||||
Aborted = true;
|
||||
WorkItem.Cancel(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the thread's stack trace.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// May return one of two stack traces. First, tries to get the thread's active stack
|
||||
/// trace. But this can fail, so as a fallback this method will return the stack
|
||||
/// trace that was active when the task was queued.
|
||||
/// </remarks>
|
||||
public string GetStackTrace()
|
||||
{
|
||||
string ret = (context == null) ? "" : ("(" + context + ") ");
|
||||
|
||||
StackTrace activeStackTrace = Util.GetStackTrace(Thread);
|
||||
if (activeStackTrace != null)
|
||||
ret += activeStackTrace.ToString();
|
||||
else if (StackTrace != null)
|
||||
ret += "(Stack trace when queued) " + StackTrace;
|
||||
// else, no stack trace available
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static long nextThreadFuncNum = 0;
|
||||
private static long numQueuedThreadFuncs = 0;
|
||||
private static long numRunningThreadFuncs = 0;
|
||||
private static Int32 threadFuncOverloadMode = 0;
|
||||
|
||||
// Maps (ThreadFunc number -> Thread)
|
||||
private static ConcurrentDictionary<long, ThreadInfo> activeThreads = new ConcurrentDictionary<long, ThreadInfo>();
|
||||
|
||||
private static readonly int THREAD_TIMEOUT = 10 * 60 * 1000; // 10 minutes
|
||||
|
||||
/// <summary>
|
||||
/// Finds threads in the main thread pool that have timed-out, and aborts them.
|
||||
/// </summary>
|
||||
private static void ThreadPoolWatchdog(object state)
|
||||
{
|
||||
foreach (KeyValuePair<long, ThreadInfo> entry in activeThreads)
|
||||
{
|
||||
ThreadInfo t = entry.Value;
|
||||
if (t.Running && !t.Aborted && (t.Elapsed() >= THREAD_TIMEOUT))
|
||||
{
|
||||
m_log.WarnFormat("Timeout in threadfunc {0} ({1}) {2}", t.ThreadFuncNum, t.Thread.Name, t.GetStackTrace());
|
||||
t.Abort();
|
||||
|
||||
ThreadInfo dummy;
|
||||
activeThreads.TryRemove(entry.Key, out dummy);
|
||||
|
||||
// It's possible that the thread won't abort. To make sure the thread pool isn't
|
||||
// depleted, increase the pool size.
|
||||
m_ThreadPool.MaxThreads++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void FireAndForget(System.Threading.WaitCallback callback, object obj)
|
||||
{
|
||||
FireAndForget(callback, obj, null);
|
||||
}
|
||||
|
||||
public static void FireAndForget(System.Threading.WaitCallback callback, object obj, string context)
|
||||
{
|
||||
WaitCallback realCallback;
|
||||
|
||||
bool loggingEnabled = LogThreadPool > 0;
|
||||
|
||||
long threadFuncNum = Interlocked.Increment(ref nextThreadFuncNum);
|
||||
ThreadInfo threadInfo = new ThreadInfo(threadFuncNum, context);
|
||||
|
||||
if (FireAndForgetMethod == FireAndForgetMethod.RegressionTest)
|
||||
{
|
||||
// If we're running regression tests, then we want any exceptions to rise up to the test code.
|
||||
@@ -1875,51 +2135,258 @@ namespace OpenSim.Framework
|
||||
// for decimals places but is read by a culture that treats commas as number seperators.
|
||||
realCallback = o =>
|
||||
{
|
||||
Culture.SetCurrentCulture();
|
||||
long numQueued1 = Interlocked.Decrement(ref numQueuedThreadFuncs);
|
||||
long numRunning1 = Interlocked.Increment(ref numRunningThreadFuncs);
|
||||
threadInfo.Started();
|
||||
activeThreads[threadFuncNum] = threadInfo;
|
||||
|
||||
try
|
||||
{
|
||||
if ((loggingEnabled || (threadFuncOverloadMode == 1)) && threadInfo.LogThread)
|
||||
m_log.DebugFormat("Run threadfunc {0} (Queued {1}, Running {2})", threadFuncNum, numQueued1, numRunning1);
|
||||
|
||||
Culture.SetCurrentCulture();
|
||||
|
||||
callback(o);
|
||||
}
|
||||
catch (ThreadAbortException e)
|
||||
{
|
||||
m_log.Error(string.Format("Aborted threadfunc {0} ", threadFuncNum), e);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[UTIL]: Continuing after async_call_method thread terminated with exception {0}{1}",
|
||||
e.Message, e.StackTrace);
|
||||
m_log.Error(string.Format("[UTIL]: Util STP threadfunc {0} terminated with error ", threadFuncNum), e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Interlocked.Decrement(ref numRunningThreadFuncs);
|
||||
threadInfo.Ended();
|
||||
ThreadInfo dummy;
|
||||
activeThreads.TryRemove(threadFuncNum, out dummy);
|
||||
if ((loggingEnabled || (threadFuncOverloadMode == 1)) && threadInfo.LogThread)
|
||||
m_log.DebugFormat("Exit threadfunc {0} ({1})", threadFuncNum, FormatDuration(threadInfo.Elapsed()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
switch (FireAndForgetMethod)
|
||||
long numQueued = Interlocked.Increment(ref numQueuedThreadFuncs);
|
||||
try
|
||||
{
|
||||
case FireAndForgetMethod.RegressionTest:
|
||||
case FireAndForgetMethod.None:
|
||||
realCallback.Invoke(obj);
|
||||
break;
|
||||
case FireAndForgetMethod.UnsafeQueueUserWorkItem:
|
||||
ThreadPool.UnsafeQueueUserWorkItem(realCallback, obj);
|
||||
break;
|
||||
case FireAndForgetMethod.QueueUserWorkItem:
|
||||
ThreadPool.QueueUserWorkItem(realCallback, obj);
|
||||
break;
|
||||
case FireAndForgetMethod.BeginInvoke:
|
||||
FireAndForgetWrapper wrapper = FireAndForgetWrapper.Instance;
|
||||
wrapper.FireAndForget(realCallback, obj);
|
||||
break;
|
||||
case FireAndForgetMethod.SmartThreadPool:
|
||||
if (m_ThreadPool == null)
|
||||
InitThreadPool(2, 15);
|
||||
m_ThreadPool.QueueWorkItem((cb, o) => cb(o), realCallback, obj);
|
||||
break;
|
||||
case FireAndForgetMethod.Thread:
|
||||
Thread thread = new Thread(delegate(object o) { realCallback(o); });
|
||||
thread.Start(obj);
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
long numRunning = numRunningThreadFuncs;
|
||||
|
||||
if (m_ThreadPool != null && LogOverloads)
|
||||
{
|
||||
if ((threadFuncOverloadMode == 0) && (numRunning >= m_ThreadPool.MaxThreads))
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref threadFuncOverloadMode, 1, 0) == 0)
|
||||
m_log.DebugFormat("Threadfunc: enable overload mode (Queued {0}, Running {1})", numQueued, numRunning);
|
||||
}
|
||||
else if ((threadFuncOverloadMode == 1) && (numRunning <= (m_ThreadPool.MaxThreads * 2) / 3))
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref threadFuncOverloadMode, 0, 1) == 1)
|
||||
m_log.DebugFormat("Threadfunc: disable overload mode (Queued {0}, Running {1})", numQueued, numRunning);
|
||||
}
|
||||
}
|
||||
|
||||
if (loggingEnabled || (threadFuncOverloadMode == 1))
|
||||
{
|
||||
string full, partial;
|
||||
GetFireAndForgetStackTrace(out full, out partial);
|
||||
threadInfo.StackTrace = full;
|
||||
threadInfo.LogThread = ShouldLogThread(partial);
|
||||
|
||||
if (threadInfo.LogThread)
|
||||
{
|
||||
m_log.DebugFormat("Queue threadfunc {0} (Queued {1}, Running {2}) {3}{4}",
|
||||
threadFuncNum, numQueued, numRunningThreadFuncs,
|
||||
(context == null) ? "" : ("(" + context + ") "),
|
||||
(LogThreadPool >= 2) ? full : partial);
|
||||
}
|
||||
}
|
||||
|
||||
switch (FireAndForgetMethod)
|
||||
{
|
||||
case FireAndForgetMethod.RegressionTest:
|
||||
case FireAndForgetMethod.None:
|
||||
realCallback.Invoke(obj);
|
||||
break;
|
||||
case FireAndForgetMethod.UnsafeQueueUserWorkItem:
|
||||
ThreadPool.UnsafeQueueUserWorkItem(realCallback, obj);
|
||||
break;
|
||||
case FireAndForgetMethod.QueueUserWorkItem:
|
||||
ThreadPool.QueueUserWorkItem(realCallback, obj);
|
||||
break;
|
||||
case FireAndForgetMethod.BeginInvoke:
|
||||
FireAndForgetWrapper wrapper = FireAndForgetWrapper.Instance;
|
||||
wrapper.FireAndForget(realCallback, obj);
|
||||
break;
|
||||
case FireAndForgetMethod.SmartThreadPool:
|
||||
if (m_ThreadPool == null)
|
||||
InitThreadPool(2, 15);
|
||||
threadInfo.WorkItem = m_ThreadPool.QueueWorkItem((cb, o) => cb(o), realCallback, obj);
|
||||
break;
|
||||
case FireAndForgetMethod.Thread:
|
||||
Thread thread = new Thread(delegate(object o) { realCallback(o); });
|
||||
thread.Start(obj);
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Interlocked.Decrement(ref numQueuedThreadFuncs);
|
||||
ThreadInfo dummy;
|
||||
activeThreads.TryRemove(threadFuncNum, out dummy);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the thread should be logged. Some very common threads aren't logged,
|
||||
/// to avoid filling up the log.
|
||||
/// </summary>
|
||||
/// <param name="stackTrace">A partial stack trace of where the thread was queued</param>
|
||||
/// <returns>Whether to log this thread</returns>
|
||||
private static bool ShouldLogThread(string stackTrace)
|
||||
{
|
||||
if (LogThreadPool < 3)
|
||||
{
|
||||
if (stackTrace.Contains("BeginFireQueueEmpty"))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a stack trace for a thread added using FireAndForget().
|
||||
/// </summary>
|
||||
/// <param name="full">Will contain the full stack trace</param>
|
||||
/// <param name="partial">Will contain only the first frame of the stack trace</param>
|
||||
private static void GetFireAndForgetStackTrace(out string full, out string partial)
|
||||
{
|
||||
string src = Environment.StackTrace;
|
||||
string[] lines = src.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
|
||||
|
||||
StringBuilder dest = new StringBuilder(src.Length);
|
||||
|
||||
bool started = false;
|
||||
bool first = true;
|
||||
partial = "";
|
||||
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
string line = lines[i];
|
||||
|
||||
if (!started)
|
||||
{
|
||||
// Skip the initial stack frames, because they're of no interest for debugging
|
||||
if (line.Contains("StackTrace") || line.Contains("FireAndForget"))
|
||||
continue;
|
||||
started = true;
|
||||
}
|
||||
|
||||
if (first)
|
||||
{
|
||||
line = line.TrimStart();
|
||||
first = false;
|
||||
partial = line;
|
||||
}
|
||||
|
||||
bool last = (i == lines.Length - 1);
|
||||
if (last)
|
||||
dest.Append(line);
|
||||
else
|
||||
dest.AppendLine(line);
|
||||
}
|
||||
|
||||
full = dest.ToString();
|
||||
}
|
||||
|
||||
#pragma warning disable 0618
|
||||
/// <summary>
|
||||
/// Return the stack trace of a different thread.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is complicated because the thread needs to be paused in order to get its stack
|
||||
/// trace. And pausing another thread can cause a deadlock. This method attempts to
|
||||
/// avoid deadlock by using a short timeout (200ms), after which it gives up and
|
||||
/// returns 'null' instead of the stack trace.
|
||||
///
|
||||
/// Take from: http://stackoverflow.com/a/14935378
|
||||
///
|
||||
/// WARNING: this doesn't work in Mono. See https://bugzilla.novell.com/show_bug.cgi?id=571691
|
||||
///
|
||||
/// </remarks>
|
||||
/// <returns>The stack trace, or null if failed to get it</returns>
|
||||
private static StackTrace GetStackTrace(Thread targetThread)
|
||||
{
|
||||
if (IsPlatformMono)
|
||||
{
|
||||
// This doesn't work in Mono
|
||||
return null;
|
||||
}
|
||||
|
||||
ManualResetEventSlim fallbackThreadReady = new ManualResetEventSlim();
|
||||
ManualResetEventSlim exitedSafely = new ManualResetEventSlim();
|
||||
|
||||
try
|
||||
{
|
||||
new Thread(delegate()
|
||||
{
|
||||
fallbackThreadReady.Set();
|
||||
while (!exitedSafely.Wait(200))
|
||||
{
|
||||
try
|
||||
{
|
||||
targetThread.Resume();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Whatever happens, do never stop to resume the main-thread regularly until the main-thread has exited safely.
|
||||
}
|
||||
}
|
||||
}).Start();
|
||||
|
||||
fallbackThreadReady.Wait();
|
||||
// From here, you have about 200ms to get the stack-trace
|
||||
|
||||
targetThread.Suspend();
|
||||
|
||||
StackTrace trace = null;
|
||||
try
|
||||
{
|
||||
trace = new StackTrace(targetThread, true);
|
||||
}
|
||||
catch (ThreadStateException)
|
||||
{
|
||||
//failed to get stack trace, since the fallback-thread resumed the thread
|
||||
//possible reasons:
|
||||
//1.) This thread was just too slow
|
||||
//2.) A deadlock ocurred
|
||||
//Automatic retry seems too risky here, so just return null.
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
targetThread.Resume();
|
||||
}
|
||||
catch (ThreadStateException)
|
||||
{
|
||||
// Thread is running again already
|
||||
}
|
||||
|
||||
return trace;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Signal the fallack-thread to stop
|
||||
exitedSafely.Set();
|
||||
}
|
||||
}
|
||||
#pragma warning restore 0618
|
||||
|
||||
/// <summary>
|
||||
/// Get information about the current state of the smart thread pool.
|
||||
/// </summary>
|
||||
@@ -1948,6 +2415,36 @@ namespace OpenSim.Framework
|
||||
|
||||
#endregion FireAndForget Threading Pattern
|
||||
|
||||
/// <summary>
|
||||
/// Run the callback on a different thread, outside the thread pool. This is used for tasks
|
||||
/// that may take a long time.
|
||||
/// </summary>
|
||||
public static void RunThreadNoTimeout(WaitCallback callback, string name, object obj)
|
||||
{
|
||||
if (FireAndForgetMethod == FireAndForgetMethod.RegressionTest)
|
||||
{
|
||||
Culture.SetCurrentCulture();
|
||||
callback(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
Thread t = new Thread(delegate()
|
||||
{
|
||||
try
|
||||
{
|
||||
Culture.SetCurrentCulture();
|
||||
callback(obj);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("Exception in thread " + name, e);
|
||||
}
|
||||
});
|
||||
|
||||
t.Name = name;
|
||||
t.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Environment.TickCount is an int but it counts all 32 bits so it goes positive
|
||||
/// and negative every 24.9 days. This trims down TickCount so it doesn't wrap
|
||||
@@ -2003,6 +2500,60 @@ namespace OpenSim.Framework
|
||||
return tcA - tcB;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats a duration (given in milliseconds).
|
||||
/// </summary>
|
||||
public static string FormatDuration(int ms)
|
||||
{
|
||||
TimeSpan span = new TimeSpan(ms * TimeSpan.TicksPerMillisecond);
|
||||
|
||||
string str = "";
|
||||
string suffix = null;
|
||||
|
||||
int hours = (int)span.TotalHours;
|
||||
if (hours > 0)
|
||||
{
|
||||
str += hours.ToString(str.Length == 0 ? "0" : "00");
|
||||
suffix = "hours";
|
||||
}
|
||||
|
||||
if ((hours > 0) || (span.Minutes > 0))
|
||||
{
|
||||
if (str.Length > 0)
|
||||
str += ":";
|
||||
str += span.Minutes.ToString(str.Length == 0 ? "0" : "00");
|
||||
if (suffix == null)
|
||||
suffix = "min";
|
||||
}
|
||||
|
||||
if ((hours > 0) || (span.Minutes > 0) || (span.Seconds > 0))
|
||||
{
|
||||
if (str.Length > 0)
|
||||
str += ":";
|
||||
str += span.Seconds.ToString(str.Length == 0 ? "0" : "00");
|
||||
if (suffix == null)
|
||||
suffix = "sec";
|
||||
}
|
||||
|
||||
if (suffix == null)
|
||||
suffix = "ms";
|
||||
|
||||
if (span.TotalMinutes < 1)
|
||||
{
|
||||
int ms1 = span.Milliseconds;
|
||||
if (str.Length > 0)
|
||||
{
|
||||
ms1 /= 100;
|
||||
str += ".";
|
||||
}
|
||||
str += ms1.ToString("0");
|
||||
}
|
||||
|
||||
str += " " + suffix;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prints the call stack at any given point. Useful for debugging.
|
||||
/// </summary>
|
||||
@@ -2222,10 +2773,15 @@ namespace OpenSim.Framework
|
||||
{
|
||||
string[] parts = firstName.Split(new char[] { '.' });
|
||||
if (parts.Length == 2)
|
||||
return id.ToString() + ";" + agentsURI + ";" + parts[0] + " " + parts[1];
|
||||
return CalcUniversalIdentifier(id, agentsURI, parts[0] + " " + parts[1]);
|
||||
}
|
||||
return id.ToString() + ";" + agentsURI + ";" + firstName + " " + lastName;
|
||||
|
||||
return CalcUniversalIdentifier(id, agentsURI, firstName + " " + lastName);
|
||||
}
|
||||
|
||||
private static string CalcUniversalIdentifier(UUID id, string agentsURI, string name)
|
||||
{
|
||||
return id.ToString() + ";" + agentsURI + ";" + name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -2260,6 +2816,38 @@ namespace OpenSim.Framework
|
||||
{
|
||||
return str.Replace("_", "\\_").Replace("%", "\\%");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the name of the user's viewer.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method handles two ways that viewers specify their name:
|
||||
/// 1. Viewer = "Firestorm-Release 4.4.2.34167", Channel = "(don't care)" -> "Firestorm-Release 4.4.2.34167"
|
||||
/// 2. Viewer = "4.5.1.38838", Channel = "Firestorm-Beta" -> "Firestorm-Beta 4.5.1.38838"
|
||||
/// </remarks>
|
||||
public static string GetViewerName(AgentCircuitData agent)
|
||||
{
|
||||
string name = agent.Viewer;
|
||||
if (name == null)
|
||||
name = "";
|
||||
else
|
||||
name = name.Trim();
|
||||
|
||||
// Check if 'Viewer' is just a version number. If it's *not*, then we
|
||||
// assume that it contains the real viewer name, and we return it.
|
||||
foreach (char c in name)
|
||||
{
|
||||
if (Char.IsLetter(c))
|
||||
return name;
|
||||
}
|
||||
|
||||
// The 'Viewer' string contains just a version number. If there's anything in
|
||||
// 'Channel' then assume that it's the viewer name.
|
||||
if ((agent.Channel != null) && (agent.Channel.Length > 0))
|
||||
name = agent.Channel.Trim() + " " + name;
|
||||
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public class DoubleQueue<T> where T:class
|
||||
@@ -2276,7 +2864,11 @@ namespace OpenSim.Framework
|
||||
|
||||
public virtual int Count
|
||||
{
|
||||
get { return m_highQueue.Count + m_lowQueue.Count; }
|
||||
get
|
||||
{
|
||||
lock (m_syncRoot)
|
||||
return m_highQueue.Count + m_lowQueue.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Enqueue(T data)
|
||||
|
||||
+550
-374
File diff suppressed because it is too large
Load Diff
@@ -82,8 +82,7 @@ namespace OpenSim
|
||||
|
||||
List<string> sources = new List<string>();
|
||||
|
||||
string masterFileName =
|
||||
startupConfig.GetString("inimaster", "OpenSimDefaults.ini");
|
||||
string masterFileName = startupConfig.GetString("inimaster", "OpenSimDefaults.ini");
|
||||
|
||||
if (masterFileName == "none")
|
||||
masterFileName = String.Empty;
|
||||
@@ -207,26 +206,13 @@ namespace OpenSim
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
// Merge OpSys env vars
|
||||
m_log.Info("[CONFIG]: Loading environment variables for Config");
|
||||
Util.MergeEnvironmentToConfig(m_config.Source);
|
||||
|
||||
// Make sure command line options take precedence
|
||||
m_config.Source.Merge(argvSource);
|
||||
|
||||
IConfig enVars = m_config.Source.Configs["Environment"];
|
||||
|
||||
if( enVars != null )
|
||||
{
|
||||
string[] env_keys = enVars.GetKeys();
|
||||
|
||||
foreach ( string key in env_keys )
|
||||
{
|
||||
envConfigSource.AddEnv(key, string.Empty);
|
||||
}
|
||||
|
||||
envConfigSource.LoadEnv();
|
||||
m_config.Source.Merge(envConfigSource);
|
||||
}
|
||||
|
||||
m_config.Source.ExpandKeyValues();
|
||||
|
||||
ReadConfigSettings();
|
||||
|
||||
return m_config;
|
||||
|
||||
@@ -45,6 +45,7 @@ using OpenSim.Framework.Servers;
|
||||
using OpenSim.Framework.Monitoring;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Services.Interfaces;
|
||||
|
||||
namespace OpenSim
|
||||
{
|
||||
@@ -271,6 +272,7 @@ namespace OpenSim
|
||||
+ " [--no-objects]"
|
||||
+ " [--rotation degrees] [--rotation-center \"<x,y,z>\"]"
|
||||
+ " [--displacement \"<x,y,z>\"]"
|
||||
+ " [--default-user \"User Name\"]"
|
||||
+ " [<OAR path>]",
|
||||
"Load a region's data from an OAR archive.",
|
||||
"--merge will merge the OAR with the existing scene (suppresses terrain and parcel info loading)." + Environment.NewLine
|
||||
@@ -399,6 +401,27 @@ namespace OpenSim
|
||||
"delete-region <name>",
|
||||
"Delete a region from disk",
|
||||
RunCommand);
|
||||
|
||||
m_console.Commands.AddCommand("Estates", false, "estate create",
|
||||
"estate create <owner UUID> <estate name>",
|
||||
"Creates a new estate with the specified name, owned by the specified user."
|
||||
+ " Estate name must be unique.",
|
||||
CreateEstateCommand);
|
||||
|
||||
m_console.Commands.AddCommand("Estates", false, "estate set owner",
|
||||
"estate set owner <estate-id>[ <UUID> | <Firstname> <Lastname> ]",
|
||||
"Sets the owner of the specified estate to the specified UUID or user. ",
|
||||
SetEstateOwnerCommand);
|
||||
|
||||
m_console.Commands.AddCommand("Estates", false, "estate set name",
|
||||
"estate set name <estate-id> <new name>",
|
||||
"Sets the name of the specified estate to the specified value. New name must be unique.",
|
||||
SetEstateNameCommand);
|
||||
|
||||
m_console.Commands.AddCommand("Estates", false, "estate link region",
|
||||
"estate link region <estate ID> <region ID>",
|
||||
"Attaches the specified region to the specified estate.",
|
||||
EstateLinkRegionCommand);
|
||||
}
|
||||
|
||||
protected override void ShutdownSpecific()
|
||||
@@ -559,7 +582,7 @@ namespace OpenSim
|
||||
{
|
||||
scene.ForEachSOG(delegate(SceneObjectGroup sog)
|
||||
{
|
||||
if (sog.AttachmentPoint == 0)
|
||||
if (!sog.IsAttachment)
|
||||
{
|
||||
sog.RootPart.UpdateRotation(rot * sog.GroupRotation);
|
||||
Vector3 offset = sog.AbsolutePosition - center;
|
||||
@@ -588,7 +611,7 @@ namespace OpenSim
|
||||
{
|
||||
scene.ForEachSOG(delegate(SceneObjectGroup sog)
|
||||
{
|
||||
if (sog.AttachmentPoint == 0)
|
||||
if (!sog.IsAttachment)
|
||||
{
|
||||
if (sog.RootPart.AbsolutePosition.Z < minZ)
|
||||
minZ = sog.RootPart.AbsolutePosition.Z;
|
||||
@@ -600,7 +623,7 @@ namespace OpenSim
|
||||
{
|
||||
scene.ForEachSOG(delegate(SceneObjectGroup sog)
|
||||
{
|
||||
if (sog.AttachmentPoint == 0)
|
||||
if (!sog.IsAttachment)
|
||||
{
|
||||
Vector3 tmpRootPos = sog.RootPart.AbsolutePosition;
|
||||
tmpRootPos.Z -= minZ;
|
||||
@@ -640,7 +663,7 @@ namespace OpenSim
|
||||
{
|
||||
scene.ForEachSOG(delegate(SceneObjectGroup sog)
|
||||
{
|
||||
if (sog.AttachmentPoint == 0)
|
||||
if (!sog.IsAttachment)
|
||||
sog.UpdateGroupPosition(sog.AbsolutePosition + offset);
|
||||
});
|
||||
});
|
||||
@@ -707,7 +730,7 @@ namespace OpenSim
|
||||
CreateRegion(regInfo, true, out scene);
|
||||
|
||||
if (changed)
|
||||
regInfo.EstateSettings.Save();
|
||||
m_estateDataService.StoreEstateSettings(regInfo.EstateSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -916,17 +939,24 @@ namespace OpenSim
|
||||
break;
|
||||
|
||||
case "regions":
|
||||
ConsoleDisplayTable cdt = new ConsoleDisplayTable();
|
||||
cdt.AddColumn("Name", ConsoleDisplayUtil.RegionNameSize);
|
||||
cdt.AddColumn("ID", ConsoleDisplayUtil.UuidSize);
|
||||
cdt.AddColumn("Position", ConsoleDisplayUtil.CoordTupleSize);
|
||||
cdt.AddColumn("Port", ConsoleDisplayUtil.PortSize);
|
||||
cdt.AddColumn("Ready?", 6);
|
||||
cdt.AddColumn("Estate", ConsoleDisplayUtil.EstateNameSize);
|
||||
SceneManager.ForEachScene(
|
||||
delegate(Scene scene)
|
||||
{
|
||||
MainConsole.Instance.Output(String.Format(
|
||||
"Region Name: {0}, Region XLoc: {1}, Region YLoc: {2}, Region Port: {3}, Estate Name: {4}",
|
||||
scene.RegionInfo.RegionName,
|
||||
scene.RegionInfo.RegionLocX,
|
||||
scene.RegionInfo.RegionLocY,
|
||||
scene.RegionInfo.InternalEndPoint.Port,
|
||||
scene.RegionInfo.EstateSettings.EstateName));
|
||||
});
|
||||
scene =>
|
||||
{
|
||||
RegionInfo ri = scene.RegionInfo;
|
||||
cdt.AddRow(
|
||||
ri.RegionName, ri.RegionID, string.Format("{0},{1}", ri.RegionLocX, ri.RegionLocY),
|
||||
ri.InternalEndPoint.Port, scene.Ready ? "Yes" : "No", ri.EstateSettings.EstateName);
|
||||
}
|
||||
);
|
||||
|
||||
MainConsole.Instance.Output(cdt.ToString());
|
||||
break;
|
||||
|
||||
case "ratings":
|
||||
@@ -975,7 +1005,7 @@ namespace OpenSim
|
||||
aCircuit.child ? "child" : "root",
|
||||
aCircuit.circuitcode.ToString(),
|
||||
aCircuit.IPAddress != null ? aCircuit.IPAddress.ToString() : "not set",
|
||||
aCircuit.Viewer);
|
||||
Util.GetViewerName(aCircuit));
|
||||
});
|
||||
|
||||
MainConsole.Instance.Output(cdt.ToString());
|
||||
@@ -1158,6 +1188,232 @@ namespace OpenSim
|
||||
SceneManager.SaveCurrentSceneToArchive(cmdparams);
|
||||
}
|
||||
|
||||
protected void CreateEstateCommand(string module, string[] args)
|
||||
{
|
||||
string response = null;
|
||||
UUID userID;
|
||||
|
||||
if (args.Length == 2)
|
||||
{
|
||||
response = "No user specified.";
|
||||
}
|
||||
else if (!UUID.TryParse(args[2], out userID))
|
||||
{
|
||||
response = String.Format("{0} is not a valid UUID", args[2]);
|
||||
}
|
||||
else if (args.Length == 3)
|
||||
{
|
||||
response = "No estate name specified.";
|
||||
}
|
||||
else
|
||||
{
|
||||
Scene scene = SceneManager.CurrentOrFirstScene;
|
||||
|
||||
// TODO: Is there a better choice here?
|
||||
UUID scopeID = UUID.Zero;
|
||||
UserAccount account = scene.UserAccountService.GetUserAccount(scopeID, userID);
|
||||
if (account == null)
|
||||
{
|
||||
response = String.Format("Could not find user {0}", userID);
|
||||
}
|
||||
else
|
||||
{
|
||||
// concatenate it all to "name"
|
||||
StringBuilder sb = new StringBuilder(args[3]);
|
||||
for (int i = 4; i < args.Length; i++)
|
||||
sb.Append (" " + args[i]);
|
||||
string estateName = sb.ToString().Trim();
|
||||
|
||||
// send it off for processing.
|
||||
IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>();
|
||||
response = estateModule.CreateEstate(estateName, userID);
|
||||
if (response == String.Empty)
|
||||
{
|
||||
List<int> estates = scene.EstateDataService.GetEstates(estateName);
|
||||
response = String.Format("Estate {0} created as \"{1}\"", estates.ElementAt(0), estateName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// give the user some feedback
|
||||
if (response != null)
|
||||
MainConsole.Instance.Output(response);
|
||||
}
|
||||
|
||||
protected void SetEstateOwnerCommand(string module, string[] args)
|
||||
{
|
||||
string response = null;
|
||||
|
||||
Scene scene = SceneManager.CurrentOrFirstScene;
|
||||
IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>();
|
||||
|
||||
if (args.Length == 3)
|
||||
{
|
||||
response = "No estate specified.";
|
||||
}
|
||||
else
|
||||
{
|
||||
int estateId;
|
||||
if (!int.TryParse(args[3], out estateId))
|
||||
{
|
||||
response = String.Format("\"{0}\" is not a valid ID for an Estate", args[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (args.Length == 4)
|
||||
{
|
||||
response = "No user specified.";
|
||||
}
|
||||
else
|
||||
{
|
||||
UserAccount account = null;
|
||||
|
||||
// TODO: Is there a better choice here?
|
||||
UUID scopeID = UUID.Zero;
|
||||
|
||||
string s1 = args[4];
|
||||
if (args.Length == 5)
|
||||
{
|
||||
// attempt to get account by UUID
|
||||
UUID u;
|
||||
if (UUID.TryParse(s1, out u))
|
||||
{
|
||||
account = scene.UserAccountService.GetUserAccount(scopeID, u);
|
||||
if (account == null)
|
||||
response = String.Format("Could not find user {0}", s1);
|
||||
}
|
||||
else
|
||||
{
|
||||
response = String.Format("Invalid UUID {0}", s1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// attempt to get account by Firstname, Lastname
|
||||
string s2 = args[5];
|
||||
account = scene.UserAccountService.GetUserAccount(scopeID, s1, s2);
|
||||
if (account == null)
|
||||
response = String.Format("Could not find user {0} {1}", s1, s2);
|
||||
}
|
||||
|
||||
// If it's valid, send it off for processing.
|
||||
if (account != null)
|
||||
response = estateModule.SetEstateOwner(estateId, account);
|
||||
|
||||
if (response == String.Empty)
|
||||
{
|
||||
response = String.Format("Estate owner changed to {0} ({1} {2})", account.PrincipalID, account.FirstName, account.LastName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// give the user some feedback
|
||||
if (response != null)
|
||||
MainConsole.Instance.Output(response);
|
||||
}
|
||||
|
||||
protected void SetEstateNameCommand(string module, string[] args)
|
||||
{
|
||||
string response = null;
|
||||
|
||||
Scene scene = SceneManager.CurrentOrFirstScene;
|
||||
IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>();
|
||||
|
||||
if (args.Length == 3)
|
||||
{
|
||||
response = "No estate specified.";
|
||||
}
|
||||
else
|
||||
{
|
||||
int estateId;
|
||||
if (!int.TryParse(args[3], out estateId))
|
||||
{
|
||||
response = String.Format("\"{0}\" is not a valid ID for an Estate", args[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (args.Length == 4)
|
||||
{
|
||||
response = "No name specified.";
|
||||
}
|
||||
else
|
||||
{
|
||||
// everything after the estate ID is "name"
|
||||
StringBuilder sb = new StringBuilder(args[4]);
|
||||
for (int i = 5; i < args.Length; i++)
|
||||
sb.Append (" " + args[i]);
|
||||
|
||||
string estateName = sb.ToString();
|
||||
|
||||
// send it off for processing.
|
||||
response = estateModule.SetEstateName(estateId, estateName);
|
||||
|
||||
if (response == String.Empty)
|
||||
{
|
||||
response = String.Format("Estate {0} renamed to \"{1}\"", estateId, estateName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// give the user some feedback
|
||||
if (response != null)
|
||||
MainConsole.Instance.Output(response);
|
||||
}
|
||||
|
||||
private void EstateLinkRegionCommand(string module, string[] args)
|
||||
{
|
||||
int estateId =-1;
|
||||
UUID regionId = UUID.Zero;
|
||||
Scene scene = null;
|
||||
string response = null;
|
||||
|
||||
if (args.Length == 3)
|
||||
{
|
||||
response = "No estate specified.";
|
||||
}
|
||||
else if (!int.TryParse(args [3], out estateId))
|
||||
{
|
||||
response = String.Format("\"{0}\" is not a valid ID for an Estate", args [3]);
|
||||
}
|
||||
else if (args.Length == 4)
|
||||
{
|
||||
response = "No region specified.";
|
||||
}
|
||||
else if (!UUID.TryParse(args[4], out regionId))
|
||||
{
|
||||
response = String.Format("\"{0}\" is not a valid UUID for a Region", args [4]);
|
||||
}
|
||||
else if (!SceneManager.TryGetScene(regionId, out scene))
|
||||
{
|
||||
// region may exist, but on a different sim.
|
||||
response = String.Format("No access to Region \"{0}\"", args [4]);
|
||||
}
|
||||
|
||||
if (response != null)
|
||||
{
|
||||
MainConsole.Instance.Output(response);
|
||||
return;
|
||||
}
|
||||
|
||||
// send it off for processing.
|
||||
IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>();
|
||||
response = estateModule.SetRegionEstate(scene.RegionInfo, estateId);
|
||||
if (response == String.Empty)
|
||||
{
|
||||
estateModule.TriggerRegionInfoChange();
|
||||
estateModule.sendRegionHandshakeToAll();
|
||||
response = String.Format ("Region {0} is now attached to estate {1}", regionId, estateId);
|
||||
}
|
||||
|
||||
// give the user some feedback
|
||||
if (response != null)
|
||||
MainConsole.Instance.Output (response);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static string CombineParams(string[] commandParams, int pos)
|
||||
{
|
||||
string result = String.Empty;
|
||||
@@ -1168,7 +1424,5 @@ namespace OpenSim
|
||||
result = result.TrimEnd(' ');
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user