Compare commits

...

608 Commits

Author SHA1 Message Date
Justin Clark-Casey (justincc) 57530c8897 minor: Make note in log if scene was restarted due to an unrecoverable physics error 2012-11-26 23:22:54 +00:00
Justin Clark-Casey (justincc) d3776e8fba Add AllowRegionRestartFromClient setting to [EstateManagement] section of OpenSim.ini.
Setting this to false will block all restart requests from the viewer even if they are otherwise legitimate.
One use is to block region restarts if necessary whilst restart functionality remains buggy or triggers bugs in modules,
though these should be fixed as soon as practicable.
Default is true, as has been the case historically.
2012-11-26 23:22:39 +00:00
Justin Clark-Casey (justincc) a124984177 Remove the redundant BypassPermissions() checks in EstateManagmentModule.
This is repeated in the PermissionsModule and checking it earlier does not allow a force override of the bypass value
2012-11-26 23:20:18 +00:00
Justin Clark-Casey (justincc) 49307ab4d1 minor: Add some console feedback on region restart and log who requested a region restart if done from the viewer. 2012-11-26 23:20:05 +00:00
Justin Clark-Casey (justincc) 2271986396 Lock on AgentCircuitData during Scene.AddClient() and RemoveClient() to prevent an inactive connection being left behind if the user closes the viewer whilst the connection is being established.
This should remove the need to run the console command "kick user --force" when these connections are left around.
2012-11-26 23:19:00 +00:00
Justin Clark-Casey (justincc) e54c11e0da Replace old Prebuild.exe accidentally added back in f977291 with one built without <copy> nant target generation and on mono 2.4.3 2012-11-15 02:51:21 +00:00
Justin Clark-Casey (justincc) 688c91308c Replace previously updated Prebuild.exe with one built directly with mono 2.4.3 2012-11-15 02:51:12 +00:00
Justin Clark-Casey (justincc) cce6e6c841 Stop Prebuild from generating <copy> statements which unnecessarily copy files into bin/Debug or bin/Release
nant_0.91~alpha2+dfsg-3_all.deb in Ubuntu 12.04 and earlier actually ignored these due to a bug
However, nant 0.92~rc1+dfsg-2 in Ubuntu 12.10 fixes this bug (possibly https://github.com/nant/nant/pull/39).
Which makes nant time-consumingly copy these files when the aren't actually used.
Tested removal of <copy> on both nant 0.91 and nant 0.92
Will be submitting this patch to prebuild project for comment though I suspect there's nobody there to pay attention.
2012-11-15 02:51:04 +00:00
Justin Clark-Casey (justincc) 8638766d79 Add [AssetService] AllowRemoteDeleteAllTypes (default false).
This allows a closed grid to delete asset types other than maptile remotely.
Only operational if AllowRemoteDelete = true also.
Defaults to false - do not enable if anybody other than you can make asset service requests.
2012-11-15 02:11:37 +00:00
Justin Clark-Casey (justincc) 7ae128abbe Move check to allow only deletion of maptiles up to AssetServerDeleteHandler from AssetService.
This allows us to use a common check for both AssetService and XAssetService.
It also allows future console commands to delete an asset.
As before, deletion of maptile assets is not allowed remotely unless this is explicitly configured.
2012-11-15 02:11:24 +00:00
Justin Clark-Casey (justincc) 6391a2fad4 minor: Adjust method doc on IXInventoryData MoveItem() and MoveFolder() to make it clear we're moving to an existing folder. 2012-11-13 04:47:24 +00:00
Justin Clark-Casey (justincc) 65d838da00 Update parent inventory folder version numbers when folders are moved/created/deleted to match version numbers cached by viewers.
This is done in the way that one would expect (e.g. moving a folder increments version number on both source and destination parent folders).
This should hopefully improve viewer reuse of its cached inventory information.
Currently MySQL only but will be implement for SQLite/MSSQL if there are no issues.
2012-11-13 04:47:17 +00:00
Justin Clark-Casey (justincc) c8ff599544 Add System.Core reference to OpenSim.Data.MySQL DLL, which is necessary to use LINQ 2012-11-08 22:05:37 +00:00
Justin Clark-Casey (justincc) 10a12b10d5 Update folder version numbers when moving items and making the Delete(string[], string[]) call (not just string, string).
This is to stop viewer inventory cache version numbers becoming out of sync with grid stored numbers when viewer performs these actions.
If there are no problems with these changes, they will be propogated to SQLite (and MSSQL if that's simple enough).
May also need to do the same on folder store/create/delete and maybe propogate version increments up the folder hierarchy, but that requires investigation.
2012-11-08 22:00:44 +00:00
Justin Clark-Casey (justincc) baddfa08f3 Increment version number of a folder when an object it contains is deleted.
Not doing this was allowing the viewer inventory cache to become out of sync if an item was directly deleted.
2012-11-08 22:00:36 +00:00
Justin Clark-Casey (justincc) f6aa262585 Lock GDI+ portion og VectorRenderModule.GetDrawStringSize() to prevent concurrent thread use provoking mono crashes.
Same rationale as commit 13690582.
2012-09-28 01:56:25 +01:00
Justin Clark-Casey (justincc) 2cc7a89012 Fix usage statement on "debug http" console command since max level is now 5 rather than 3 2012-09-13 00:20:38 +01:00
Justin Clark-Casey (justincc) 108e77fe1a Fix bug in logging sample input at debug http level 4.
Also converts newlines to "\n" text.
2012-09-13 00:20:31 +01:00
Justin Clark-Casey (justincc) 97b1b309ce minor: Comment out friends notification log spam for now. 2012-09-13 00:20:21 +01:00
Justin Clark-Casey (justincc) 53839ac779 Make "show http-handlers" command available for ROBUST instances as well as the simulator executable. 2012-09-13 00:20:09 +01:00
Justin Clark-Casey (justincc) 4efcf38e17 Add levels 4 and 5 to "debug http" console command that will log a sample of incoming request data and the entire incoming data respectively.
See "help debug http" for more details.
2012-09-13 00:20:01 +01:00
Justin Clark-Casey (justincc) 639d147231 Add missing DynamicTexture.cs file from last commit 2012-09-13 00:19:45 +01:00
Justin Clark-Casey (justincc) a53f90cf7a If reusing dynamic textures, do not reuse small data length textures that fall below current viewer discard level 2 thresholds.
Viewer LL 3.3.4 and before sometimes fail to properly redisplay dynamic textures that have a small data length compared to pixel size when pulled from cache.
This appears to happen when the data length is smaller than the estimate discard level 2 size the viewer uses when making this GetTexture request.
This commit works around this by always regenerating dynamic textures that fall below this threshold rather than reusing them if ReuseDynamicTextures = true
This can be controlled by the [Textures] ReuseDynamicLowDataTextures config setting which defaults to false.
2012-09-13 00:19:39 +01:00
Justin Clark-Casey (justincc) e0a3a8d47b If the GetTexture capability receives a request for a range of data beyond that of an otherwise valid asset, return HTTP PartialContent rather than RequestedRangeNotSatisfiable.
This is because recent viewers (3.2.1, 3.3.4) and probably earlier ones using the http GetTexture capability will sometimes make such invalid range requests.
This appears to happen if the viewer's estimate of texture sizes at discard levels > 0 (chiefly 2) exceeds the total texture size.
I believe this does not normally happen but can occur for dynamic textures with are large but mainly blank.
If this happens, returning a RequestedRangeNotSatisfiable will cause the viewer to not render the texture at the final resolution.
However, returning a PartialContent (or OK) even with 0 data will allow the viewer to render the final texture.
2012-09-13 00:19:26 +01:00
Justin Clark-Casey (justincc) 7ce30cc49e Make ReuseDynamicTextures an experimental config setting in [Textures]. Default is false, as before.
If true, this setting reuses dynamically generated textures (i.e. created through osSetDynamicTextureData() and similar OSSL functions) where possible rather than always regenerating them.
This results in much quicker updates viewer-side but may bloat the asset cache (though this is fixable).
Also, sometimes issue have been seen where dynamic textures do not transfer to the viewer properly (permanently blurry).
If this happens and that flag is set then they are not regenerated, the viewer has to clear cache or wait for 24 hours before all cached uuids are invalidated.
CUrrently experimental.  Default is false, as before.
2012-09-13 00:19:12 +01:00
Justin Clark-Casey (justincc) 6c36471f0c If the compile-time DynamicTextureModule.ReuseTextures flag is set, check metadata still exists for any reused asset in case some other process has removed it from the cache. 2012-09-13 00:19:05 +01:00
Justin Clark-Casey (justincc) a100723aaf Renaming existing 'torture' tests to 'performance' tests instead, since this better matches what they really do.
nant target name changes to test-perf instead of torture, to match test-stress
still not run by default
2012-09-13 00:18:56 +01:00
Justin Clark-Casey (justincc) 69dc9b89a2 Add VectorRenderModuleStressTests that contains a long running test that generates thousands of vector textures concurrently.
Intended for use if there are future issues with mono crashes whilst generate dynamic textures.
This test is triggered via a new test-stress nant target.
Not run by default.
2012-09-13 00:18:48 +01:00
Justin Clark-Casey (justincc) c0d68d0aa4 Add experimental DynamicTextureModule.ReuseTextures flag, currently only configurable on compile.
Disabled (status quo) by default.
This flag makes the dynamic texture module reuse cache previously dynamically generated textures given the same input commands and extra params for 24 hours.
This occurs as long as those commands would always generate the same texture (e.g. they do not contain commands to fetch data from the web).
This makes texture changing faster as a viewer-cached texture uuid is sent and may reduce simulator load in regions with generation of lots of dynamic textures.
A downside is that this stops expiry of old temporary dynamic textures from the cache,
Another downside is that a jpeg2000 generation that partially failed is currently not regenerated until restart or after 24 hours.
2012-09-13 00:18:29 +01:00
Justin Clark-Casey (justincc) ce89bc38e1 Add VectorRenderModule.TestRepeatSameDrawDifferentExtraParams() 2012-09-13 00:18:07 +01:00
Justin Clark-Casey (justincc) a21ee11fe8 Add VectorRenderModuleTests.TestRepeatDrawContainingImage() 2012-09-13 00:18:00 +01:00
Justin Clark-Casey (justincc) 06df03d98a Add VectorRenderModuleTests.TestRepeatDraw() 2012-09-13 00:17:47 +01:00
Justin Clark-Casey (justincc) 2f4181623d Add IDynamicTextureManager.ConvertData() to match AsyncConvertData(). Remove mismatching ConvertStream() where there is no AsyncConvertStream and neither IDynamicTextureManager implementer implements this method. 2012-09-13 00:13:22 +01:00
Justin Clark-Casey (justincc) bbfb501b02 minor: Simplify return of vector render module name and some very minor removal of unncessary syntax clutter 2012-09-13 00:13:13 +01:00
Justin Clark-Casey (justincc) a70baa95d1 Lock disposal of separate gdi+ objects under different threads since this prevents malloc heap corruption seen under Ubuntu 10.04.1 and 11.04 - probably a libcairo issue
In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously,
the native malloc heap can become corrupted, possibly due to a double free().  This may be due to
bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX.  These problems were
seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1.  They go away if disposal is perfomed
under lock.
2012-08-22 23:09:33 +01:00
Justin Clark-Casey (justincc) ed99017271 Tighten up OpenSim.Framework.Cache locking to avoid race conditions.
This is to resolve a reported issue in http://opensimulator.org/mantis/view.php?id=6232
Here, the land management module is using OpenSim.Framework.Cache (the only code to currently do so apart from the non-default CoreAssetCache).
2012-08-21 22:23:34 +01:00
Justin Clark-Casey (justincc) 061c748b75 Add --force flag to "kick user" console command to allow bypassing of recent race condition checks.
This is to allow a second attempt to remove an avatar even if "show connections" shows them as already inactive (i.e. close has already been attempted once).
You should only attempt --force if a normal kick fails.
This is partly for diagnostics as we have seen some connections occasionally remain on lbsa plaza even if they are registered as inactive.
This is not a permanent solution and may not work anyway - the ultimate solution is to stop this problem from happening in the first place.
2012-08-21 22:23:04 +01:00
Justin Clark-Casey (justincc) c4645a899f Add information to ThreadStackSize about possibly increasing if suffering StackOverflowExceptions during script conversion/compilation (e.g. on Windows 64-bit) 2012-08-21 22:15:17 +01:00
Justin Clark-Casey (justincc) c223ac6929 minor: Make xengine debug message on script load a scripting loading message instead.
This is more useful if compilation fails due to an uncatchable exception since we know what was being compiled.
2012-08-21 22:14:56 +01:00
Melanie 7e287227a4 Release http-in URLs when llResetScript is called 2012-08-21 22:12:48 +01:00
Justin Clark-Casey (justincc) d4470c6147 Fix the recent windows compile error by putting newFont for case "R" in VectorRenderModule inside its own context, rather than disposing of the old font before using it as a prototype for the new. 2012-08-21 22:11:53 +01:00
SignpostMarv c14f983cca attempting to fix a build issue
Signed-off-by: BlueWall <jamesh@bluewallgroup.com>
2012-08-21 22:11:39 +01:00
Justin Clark-Casey (justincc) 8a78d0f974 Delete old blank SOGSpamTest 2012-08-21 22:09:00 +01:00
Justin Clark-Casey (justincc) f35e94f168 Properly dispose of all GDI+ entities used in VectorRenderModule for dynamic textures.
The convention is that if an object implements IDiposable() the code must explicitly call Dispose() or call it via the using statement.
This may be particularly important for GDI+ objects since they encapsulate native code entities.
2012-08-21 22:08:49 +01:00
Justin Clark-Casey (justincc) 0e9e60d55a Remove duplicated IScenePresence.PresenceType. This is already in ISceneAgent.PresenceType from which IScenePresence inherits.
No other code changes required.
2012-08-21 22:06:31 +01:00
Justin Clark-Casey (justincc) f6a7325961 Add information about each column to "show queues" region console command help. 2012-08-21 22:00:38 +01:00
Justin Clark-Casey (justincc) ed63cafa65 Extend region console "show queues" command to show already collected time since last packeted received by the simulator from a viewer. 2012-08-21 22:00:31 +01:00
Justin Clark-Casey (justincc) 092e94035b Backport fix of inventory skeleton fetch from XInventoryServicesConnector.
This is not used by login if the inventory service and login service are housed in the same ROBUST instance (which is the default config)
2012-08-02 01:55:44 +01:00
Justin Clark-Casey (justincc) fa3ebd85c9 minor: Comment out noisy ScriptTaskInventory Request log message 2012-08-02 01:36:37 +01:00
Justin Clark-Casey (justincc) 08a9b01123 Fix a bug in pCampbot grabbing behaviour where an exception would be thrown if the bot was not yet aware of any objects. 2012-08-02 01:35:31 +01:00
Justin Clark-Casey (justincc) 5772d23ff6 Look up the NPC module when the SensorRepeat class is created, rather than on every single sensor sweep. 2012-08-02 01:34:53 +01:00
Justin Clark-Casey (justincc) 1d0ff7da2a Resolve a deadlock between INPCModule and SensorRepeat by replacing the SensorRepeat list with a new list on add/removes rather than locking it for the duration of the sensor sweep.
A deadlock was observed today where NPC removal on a script thread would lock the NPC list and then try to lock the sensor list via scripted attachment removal.
Concurrently, the sensor sweep thread would lock the sensor list and then try to lock the NPC list to check NPC status.
This commit resolves the deadlock by replacing the sensor list on update rather than locking it for the duration of the sweep.
2012-08-02 01:30:35 +01:00
Justin Clark-Casey (justincc) ec063b9088 Fix bug in SoundModule.TriggerSound() where every sound update to an avatar would base its gain calculation on the previous avatar's gain, instead of the original input gain.
This was making sound attenuate oddly when there were NPCs in the region, though it could also happen with ordinary avatars.
2012-08-02 01:30:27 +01:00
Justin Clark-Casey (justincc) 12fbfb6125 If we're fetching active gestures via the XInventoryServiceConnector, then properly look at the ITEMS dictionary already returned rather than the level above this. 2012-08-02 01:30:17 +01:00
SignpostMarv 272cd9886d adding asset cache and map tile directories to .gitignore 2012-08-02 01:29:22 +01:00
Justin Clark-Casey (justincc) 627cfe6678 Remove the LandGeom checks in OdeScene - these are pointless since LandGeom is always IntPtr.Zero and contacts returned always have a valid geometry.
Possibly this was for a feature that was never implemented or was otherwise removed.
Thanks to SignpostMarv for the spot of the warning that shows this parameter was never changed.
2012-08-02 01:28:21 +01:00
Justin Clark-Casey (justincc) aac4d9d682 Fix issue where RegionCombinerModule was not removing regions from its dictionary on RemoveRegion(), causing a later issue if regions were restarted (removed then readded). 2012-08-02 01:27:17 +01:00
Justin Clark-Casey (justincc) 25d39a19e1 When copying items, copy the item description field instead of the asset description field.
If we copy the asset description then we will only ever replicate the very first description, if there was one, not any subsequent changes.
Thanks to Oren Hurvitz of Kitely for this patch from http://opensimulator.org/mantis/view.php?id=6107
I have adapted it slightly to change the order of arguments (name before description rather than vice-versa) and slightly improve some method doc.
2012-08-02 01:27:03 +01:00
Justin Clark-Casey (justincc) 55d383e4be Add MemoryWatchdog class missing from git master a1e9964 2012-08-02 01:19:01 +01:00
Justin Clark-Casey (justincc) b180fdd0fd Correct churn stat from MB/s from KB/s 2012-08-02 01:18:48 +01:00
Justin Clark-Casey (justincc) cc6b2fdb9f Add experimental "OpenSim object memory churn" statistics to output of region console "show stats" command
This aims to capture the amount of memory that OpenSim turns over whilst operating a region.
This memory is not lost - apart from leaks it is reclaimed by the garbage collector.
However, the more memory that gets turned over the more work the GC has to do to reclaim it.
2012-08-02 01:13:58 +01:00
Justin Clark-Casey (justincc) 9d6ea27df0 Make SceneManager.OnRegionsReadyStatusChange event available.
This is fired when all regions are ready or when at least one region becomes not ready.
Recently added EventManager.OnRegionReady becomes OnRegionReadyStatusChange to match OnLoginsEnabledStatusChange
2012-08-02 00:50:02 +01:00
Melanie 2d66fcd4cd Committing Avination's memleak fix-a-thon, installment #2
Ensure items coming off the lockless queue are released. Also ensure this
is done when the queue is cleared.
2012-08-02 00:24:23 +01:00
Melanie 91ae1908fe Committing Avination's memleak fix-a-thon, installment #3
When linking, detach the no longer used SOG's from backup so they can be
collected. Since their Children collection is never emptied, they prevent
their former SOPs from being collected as well.
2012-08-02 00:23:47 +01:00
Melanie ed962bb3d3 Commiting Avination's memleak fix-a-thon, installment #1
As the MinHeap shrinks, free object references that have been sent. Also,
free the last item when it empties.
2012-08-02 00:23:38 +01:00
Justin Clark-Casey (justincc) 9ea09d785c Add basic TestCreateRootScenePresence() regression test 2012-08-02 00:18:45 +01:00
Justin Clark-Casey (justincc) e3db5fb603 Add EventManager.OnRegionLoginsStatusChange fired whenever logins are enabled or disabled at any point, not just during initial startup.
This replaces EventManager.OnLoginsEnabled which only fired when logins were first enabled
and was affected by a bug where it would never fire if the region started with logins disabled.
2012-08-02 00:11:11 +01:00
Justin Clark-Casey (justincc) 58aa51218e Add back notification to neighbouring regions when RegionReadyModule is not active accidentally just removed in 528004d 2012-08-02 00:11:00 +01:00
Justin Clark-Casey (justincc) 0fff0e1fad Perform other region ready actions even if simulator is configured to leave logins disabled on startup. 2012-08-02 00:10:46 +01:00
Justin Clark-Casey (justincc) 4457ec667a Stop the 15 second initial script compile wait if a script is being rezzed on a previously empty region. 2012-08-02 00:07:41 +01:00
Justin Clark-Casey (justincc) 7f2e6a55c4 Fix bug where region ready would be triggered a second time if a script was rezzed on a previously script-free region.
There is no need to listen for OnRezScript in RegionReadyModule since OnEmptyScriptCompileQueue will only fire if scripts were compiled.
2012-08-02 00:07:27 +01:00
Justin Clark-Casey (justincc) 92a01a7e70 Fix bug where region ready was being triggered twice in quick succession if a region contained no scripts. 2012-08-02 00:04:37 +01:00
Justin Clark-Casey (justincc) 4debc67b48 Establish EventManager.OnRegionReady event. This will only be triggerred once when the region is ready.
Switch MapImageServiceModule to use this.
2012-08-02 00:04:17 +01:00
Justin Clark-Casey (justincc) c8f60acc30 Pass entire scene object in OnLoginsEnabled event rather than just the region name.
This saves listeners from having to re-retrieve the scene from their own lists, which won't work anyway if multiple regions with the same name have been allowed
2012-08-01 23:59:47 +01:00
Justin Clark-Casey (justincc) 272c3c1069 Only listen to LoginsEnabled event in RegionReadyModule if it has been asked to disable logins until all scripts have been compiled 2012-08-01 23:50:59 +01:00
Justin Clark-Casey (justincc) 5aa9c21e7d minor: switch around mixed up circuit code and endpoint data in "show connections" region console command 2012-07-25 23:37:21 +01:00
Justin Clark-Casey (justincc) 454c3fc913 Make LLClientView instant message handling asynchronous rather than synchronous to prevent long operations from holding up all inbound packet processing.
Giving a large folder from one avatar to another was causing a long delay when handled synchronously, since it took some time to retrieve the necessary data from the inventory service.
Handling this asynchronously instead stops this delay from disrupting all avatars in the scene.  This has been shown in OSGrid.
I see no reason for not handling all IM messages asynchronously, just as incoming chat is handled asynchronously, so this has been switched for all instant messages.
Thanks to Nebadon for testing this change out.
2012-07-25 23:37:20 +01:00
Justin Clark-Casey (justincc) 3cd7c59696 Comment out OnIncomingInstantMessage and OnInstantMessage handlers in GroupsModule, since these led to a private blank method 2012-07-25 23:37:18 +01:00
Justin Clark-Casey (justincc) 1f8ac33ecb Stop explicitly closing and nulling out Animator in order to prevent NREs in various places due to race conditions.
Even where checks are being made they aren't enough since they all assume that the Animator they just checked is still there in the next line, which is not necessarily the case without locking.
The memory used is small and these should be GC'd anyway when the SP is released.  If this is not happening then the wider problem of old SPs being retained needs to be resolved.
2012-07-25 23:37:15 +01:00
Justin Clark-Casey (justincc) 47e2922a40 Prevent race conditions between two threads that call LLClientView.Close() simultaneously (e.g. ack timeout and an attempt to reconnect) 2012-07-25 23:32:27 +01:00
Justin Clark-Casey (justincc) 4deb25da87 Add TestCreateDuplicateRootScenePresence() regression test. 2012-07-25 23:32:21 +01:00
Justin Clark-Casey (justincc) 587c8017ab Add basic TestCreateRootScenePresence() regression test 2012-07-25 23:32:06 +01:00
Justin Clark-Casey (justincc) d5d801f218 Close() the ScenePresence after we've removed it from the scene graph, to cut down race conditions when another thread manages the grab the presence after some SP structures have been reset. 2012-07-25 23:30:59 +01:00
Justin Clark-Casey (justincc) 2f865da5c7 refactor: factor out common code in WebStatsModule.OnMakeRootAgent() 2012-07-19 01:00:50 +01:00
Justin Clark-Casey (justincc) cf2f6843c6 In WebStatsModule.OnMakeRootAgent(), get region ID directly from SP.Scene.RegionInfo.RegionID instead of manually looking it up from the stored scene list. 2012-07-19 01:00:40 +01:00
Justin Clark-Casey (justincc) 97d084c9f5 Stop warning about no session from ViewerStats if user teleports to another region in the same simulator that was not next to the source region.
This was because teleporting to the new region invoked the new session setup code before the agent was removed from the old region, which then invoked the session teardown code.
Now, we only invoke the teardown code if the region ID occupied by the agent being removed is the same as the one registered for the current session.
2012-07-19 01:00:33 +01:00
Justin Clark-Casey (justincc) 14f72a9a43 Remove a callstack print out I accidentally left in 2 commits ago in 9ccb578 2012-07-19 00:57:50 +01:00
Justin Clark-Casey (justincc) 89efccaa71 Rather than instantiating a UTF8 encoding everywhere when we want to supress the BOM, use a single Util.UTF8NoBomEncoding.
This class is thread-safe (as evidenced by the provision of the system-wide Encoding.UTF8 which does not suppress BOM on output).
2012-07-19 00:57:36 +01:00
Justin Clark-Casey (justincc) 8f61da0759 Don't cache regions data on the other unused LocalGridServiceConnector that the module code still sets up even if we're using one directly instantiated from the RemoteGridServiceConnector.
Also improves log messages to indicate which regions are sending/receiving various neighbour protocol messages.
2012-07-19 00:50:17 +01:00
Justin Clark-Casey (justincc) e88e87ff63 Stop redundantly passing in the endpoint to the LLClientView constructor.
This can always be retrieved via the LLUDPClient and is so done in various places already.
2012-07-19 00:45:19 +01:00
Justin Clark-Casey (justincc) 4f10d1aa0c Remove IClientIPEndpoint client interface for now.
This may well come back in the future when this subinterface is actually used but it currently isn't and I feel the name was poor.
Everything uses IClientAPI.RemoveEndPoint which also returned the full endpoint rather than just the ip address.
2012-07-19 00:45:08 +01:00
Justin Clark-Casey (justincc) 1912215c40 Remove IClientAPI.GetClientEP() in favour of existing identical IClientAPI.RemoteEndpoint. 2012-07-19 00:45:02 +01:00
Justin Clark-Casey (justincc) ffbca99b57 Extend "show circuits" to show circuit code, ip and viewer name.
Also change to use standard table formatting
"show circuits" and "show connections" console commands are very similar but access different data structures.
2012-07-19 00:44:48 +01:00
Justin Clark-Casey (justincc) f660a25fa7 Add active status to "show connections" 2012-07-19 00:40:35 +01:00
Justin Clark-Casey (justincc) 523d03fb76 Put output for "show connections" command into standard table format.
Also moves into own method.
2012-07-19 00:40:18 +01:00
Justin Clark-Casey (justincc) 85985a8c3e Where possible, use the system Encoding.ASCII and Encoding.UTF8 rather than constructing fresh copies.
The encodings are thread-safe and already used in such a manner in other places.
This isn't done where Byte Order Mark output is suppressed, since Encoding.UTF8 is constructed to output the BOM.
2012-07-19 00:25:40 +01:00
Justin Clark-Casey (justincc) 013e002b00 Fix build break for windows with missing package for IScriptEngine in prebuild.xml for OpenSim.Region.CoreModules.Tests.dll 2012-07-11 23:29:45 +01:00
Justin Clark-Casey (justincc) 5269d77cf9 Allow XEngine StartDelay to be configured in the [XEngine] config section.
This is only currently meant for use by regression tests that don't have any issues if XEngine is started up quickly, since no other operations will be occuring simultaneously.
Therefore, this is not yet documented externally.
2012-07-11 23:29:39 +01:00
Justin Clark-Casey (justincc) 8c8e6220fb Remove WorldComm module from the regression TestCompileAndStartScript() since the infrastructure no longer fails if this module isn't present, at least on the tested codepaths 2012-07-11 23:29:31 +01:00
Justin Clark-Casey (justincc) 150860c964 Add regression TestDetachScriptedAttachmentToInventory()
This currently only does a relatively crude check for a ScriptState node in the serialized xml
2012-07-11 23:29:24 +01:00
Justin Clark-Casey (justincc) 0cb1b0bb4a Add regression TestRezScriptedAttachmentsFromInventory() though this currently only checks for the presence of script items, not for started scripts 2012-07-11 23:29:16 +01:00
Justin Clark-Casey (justincc) 56d894ae24 refactor: move management of SOP.SitTargetAvatar into SOP.AddSittingAvatar() and SOP.RemoveSittingAvatar() 2012-07-11 23:29:07 +01:00
Justin Clark-Casey (justincc) b34fd50155 Revert "refactor: Add SOP.IsSitTargetOccupied to improve readability"
This reverts commit c8f0d476d2.
On reconsideration, I think this is less readable since immediately following code still sets SitTargetAvatar directly
2012-07-11 23:15:35 +01:00
Justin Clark-Casey (justincc) 74486e767d refactor: Add SOP.IsSitTargetOccupied to improve readability 2012-07-11 23:15:23 +01:00
Justin Clark-Casey (justincc) 1b8814878d refactor: use sit orientation argument passed in to SP.SendSitResponse() rather than creating a new copy
There are no issues with side-effects since this is a struct.
2012-07-11 23:15:14 +01:00
Justin Clark-Casey (justincc) 095375d63d Move common code to detect whether a part has a valid sit target into a SOP property rather than being repeated in SP.
This also makes the detection in SP.FindNextAvailableSitTarget() and SendSitResponse() identical.
Previously they varied slightly (SendSitResponse didn't check for an older type of invalid quaternion) but the practical effect is most probably zero.
2012-07-11 23:15:06 +01:00
Justin Clark-Casey (justincc) cb4e074a8c Remove log line accidentally left in SP.SendSitResponse() 2012-07-11 23:14:59 +01:00
Justin Clark-Casey (justincc) 222f844d65 Disable logging in regression test in OSSL_ApiAttachmentTests 2012-07-11 23:14:52 +01:00
Justin Clark-Casey (justincc) bb2a9060f1 Fix recent SOP.GetSittingAvatars() to return null if there are no sitting avatars rather than throwing an exception.
Extends sitting avatar regression tests to test new sitters information
2012-07-11 23:14:45 +01:00
Justin Clark-Casey (justincc) e21dd88ed5 When an attachment is detached to inv or derezzed, stop the scripts, update the known item with script state still in the script engine and then remove the scripts.
This is to fix a regression starting from 5301648 where attachments had to start being deleted before persistence in order to avoid race conditions with hud update threads.
2012-07-11 23:14:36 +01:00
Justin Clark-Casey (justincc) 35457448ca If a script is being stopped manually, then give the scriptpool thread 1 second to finish normally before forcibly aborting.
This is to avoid the worst of the problems in mono 2.6, 2.10 where an aborted thread does not always release all its locks.
This very short grace period is identical to the existing behaviour when a script is removed from the scene.
2012-07-11 23:14:30 +01:00
Justin Clark-Casey (justincc) 596caf41db This script allows an object to be attached directly from prim inventory to another avatar in the scene.
Very useful in serious game/environment scenarios where its only allowed for trusted creators.
Threat level Severe
2012-07-11 23:14:14 +01:00
Justin Clark-Casey (justincc) c62b46a167 Don't allow a prim to be sat upon if its part of an attachment 2012-07-11 23:14:04 +01:00
Justin Clark-Casey (justincc) 2b3098f011 Do not allow a script to attach a prim if its being sat upon.
This prevents a stack overflow where a get position on the avatar will refer to the attachment which will in turn refer back to the avatar.
This required recording of all sitting avatars on a prim which is done separately from recording the sit target avatar.
Recording HashSet is null if there are no sitting avatars in order to save memory.
2012-07-11 23:13:48 +01:00
Justin Clark-Casey (justincc) 74b4efd7f9 minor: remove some recent mono compiler warnings 2012-07-11 23:07:17 +01:00
Justin Clark-Casey (justincc) 298c4c0eb5 Remove duplicate Warp3DImageModule entry in CoreModulePlugin.addin.xml
This was causing 2 copies of the module to be created for each scene.
Probably no bad consequences other than a small waste of memory (both for the module and for the warp3D renderer it loaded)
2012-07-11 23:07:09 +01:00
Justin Clark-Casey (justincc) 068917bc29 Remove redundant SetScene() function in Scene.AddSceneObject()
This is always done later on in SceneGraph.AddSceneObject() if the call hasn't failed due to sanity checks.
There's no other purpose for this method to exist and it's dangerous/pointless to call in other conditions.
2012-07-11 23:06:41 +01:00
Justin Clark-Casey (justincc) d8f1d2892c Remove now duplicate interregion object check that should have been removed a few commits ago in 43a2da9 2012-07-11 23:06:30 +01:00
Justin Clark-Casey (justincc) ccf8e89193 minor: Remove some wrong comments in attachments regression tests 2012-07-11 23:06:23 +01:00
Justin Clark-Casey (justincc) f17f58ac2a Add assert to attachment regression tests to check that number of objects in the scene graph 2012-07-11 23:06:14 +01:00
Justin Clark-Casey (justincc) 6bcb5baab6 Pull prim crossing/teleport checks up into Scene.IncomingCreateObject() from Scene.AddObject()
Only IncomingCreateObject() needs these checks.  General object adding does not need to perform crossing perm checks
2012-07-11 23:05:59 +01:00
Justin Clark-Casey (justincc) 0aaf935333 refactor: extract method UpdateUserInventoryWithAttachment() from AttachObject() for better code comprehension 2012-07-11 23:05:53 +01:00
Justin Clark-Casey (justincc) b30806822e Log MONO_THREADS_PER_CPU value on simulator startup, or "unset" if it is not set 2012-07-11 23:05:43 +01:00
Justin Clark-Casey (justincc) a2c3dfc422 Log warning if time between invocations of the watchdog thread is twice the timer setting.
This is to help detect situations where thread timeout warnings are being generated because of general machine issues rather than deadlock, network or other problems.
2012-07-11 23:05:34 +01:00
Justin Clark-Casey (justincc) 4050a6f8bb minor: add client name to various login service log messages to disambiguate messages from concurrent logins. Also adds destination resolution debug log message showing region endpoint.
Adding endpoint to the log helps to find issues where the region external host information has been wrongly configured
2012-07-11 23:05:26 +01:00
Justin Clark-Casey (justincc) 0d0d04c484 minor: Add more information to OSFunctionThreatLevel and clarify some text in using PARCEL_OWNER, PARCEL_GROUP_MEMBER, ESTATE_MANAGER, ESTATE_OWNER permission categories 2012-07-11 23:05:09 +01:00
SignpostMarv 952b3448a6 porting console commands from raw2sculpt 3.2 2012-07-11 23:05:01 +01:00
Justin Clark-Casey (justincc) d53ef3b302 Add OSSL function osForceAttachToAvatarFromInventory()
This works like osForceAttachToAvatar() but allows an object to be directly specified from the script object's inventory rather than forcing it to be rezzed in the scene first.
Still only attaches objects to the owner of the script.
This allows one to bypass the complicated co-ordination of first rezzing objects in the scene before attaching them.
Threat level high.
2012-07-11 23:04:49 +01:00
Justin Clark-Casey (justincc) 48e88397a0 Use GetInventoryItem() in llRezAtRoot rather than iterating through a cloned dictionary 2012-07-11 23:04:42 +01:00
Justin Clark-Casey (justincc) 976190fe96 refactor: In llGetNotecardLine() use existing GetInventoryItem() rather than inspecting a clone of the TaskInventory dictionary that was not cloned thread-safe 2012-07-11 23:04:34 +01:00
Justin Clark-Casey (justincc) 1e025d6074 refactor: In llGetNumberOfNotecardLines() use existing GetInventoryItem() rather than inspecting a clone of the TaskInventory dictionary that was not cloned thread-safe 2012-07-11 23:04:27 +01:00
Justin Clark-Casey (justincc) fffd2fe10d refactor: use existing GetInventoryItem() in GetScriptByName(), itself renamed from ScriptByName() 2012-07-11 23:01:41 +01:00
Justin Clark-Casey (justincc) cf8adbe007 refactor: In llGetInventoryType() use existing GetInventoryItem() 2012-07-11 23:01:33 +01:00
Justin Clark-Casey (justincc) 890f617e58 refactor: In llGetInventoryCreator() use existing GetInventoryItem() 2012-07-11 23:01:27 +01:00
Justin Clark-Casey (justincc) 6ff0e58db7 refactor: In llGetInventoryPermMask() use existing GetInventoryItem() 2012-07-11 23:00:57 +01:00
Justin Clark-Casey (justincc) 795443cff1 refactor: in llGetInventoryPermMask use existing GetInventoryItem() 2012-07-11 23:00:50 +01:00
Justin Clark-Casey (justincc) 8c7f511e55 refactor: In llRemoteLoadScriptPin() use existing GetInventoryItem() 2012-07-11 23:00:43 +01:00
Justin Clark-Casey (justincc) 0acac2f890 refactor: replace use of LSL_Api.GetTaskInventoryItem() with existing GetInventoryItem() 2012-07-11 23:00:36 +01:00
Justin Clark-Casey (justincc) 72554fc5b8 refactor: In llGetInventoryKey() use existing GetInventoryItem() 2012-07-11 23:00:28 +01:00
Justin Clark-Casey (justincc) aa1442b07e In llMessageLinked() use GetInventoryItems() rather than cloning TaskInventory directory
GetInventoryItems() returns a new list and so is equivalent, and creates this list under lock whereas Clone() is not thread-safe
2012-07-11 23:00:21 +01:00
Justin Clark-Casey (justincc) e8a0ec1287 In llRequestInventoryData() use GetInventoryItems() rather than cloning TaskInventory directory
GetInventoryItems() returns a new list and so is equivalent, and creates this list under lock whereas Clone() is not thread-safe
2012-07-11 23:00:13 +01:00
Justin Clark-Casey (justincc) 3436be2046 refactor: In llCollisionSound() use existing GetInventoryItem() method rather than have it iterate through TaskInventory itself. 2012-07-11 23:00:07 +01:00
Justin Clark-Casey (justincc) 9a0bcb7750 refactor: In llRemoveInventory() use existing GetInventoryItem() method rather than have it iterate through TaskInventory itself. 2012-07-11 22:59:59 +01:00
Justin Clark-Casey (justincc) 218fe36f84 refactor: make llGiveInventory() use existing GetInventoryItem() method rather than iterate through TaskInventory itself. 2012-07-11 22:59:53 +01:00
Justin Clark-Casey (justincc) 07298c8b4f refactor: rename Watchdog.WATCHDOG_TIMEOUT_MS to DEFAULT_WATCHDOG_TIMEOUT_MS to reflect what it actually is 2012-07-11 22:59:46 +01:00
Justin Clark-Casey (justincc) d9f40d1ebc minor: Add some method doc to HasGroupChanged and Schedule GroupForFull/PartUpdate() to indicate when region modules need to invoke them 2012-07-11 22:59:39 +01:00
Justin Clark-Casey (justincc) eddff428ed Removing unused handling of incoming create object by userID and itemID only.
It appears this was never actually used since attachments were rezzed in other code.
This was never available on remote simulator comms, only local.
2012-07-11 22:58:57 +01:00
Justin Clark-Casey (justincc) 61aaa10460 Remove code listed for removal in 0.7.3 that handled script restart for incoming attachments from pre-fatpack regions (versions of OpenSimulator more than a year old) 2012-07-11 22:58:50 +01:00
Justin Clark-Casey (justincc) e1d6929e61 Move update of the final optional ODE total frame stat inside the OdeLock rather than outside to avoid a very occasional race condition with the stat collection thread 2012-07-11 22:58:37 +01:00
Justin Clark-Casey (justincc) 6b87873aa7 refactor: rename _collisionEventPrim to m_collisionEventActors and _collisionEventPrimChanges to m_collisionEventActorsChanges to reflect their actual contents.
These dictionaries handle all actor types, not just physical prims.
2012-07-11 22:58:29 +01:00
Justin Clark-Casey (justincc) f690acbfb6 Fix a regression where we stopped removing avatars from collision event reporting on logout, rather than stopping clearing their collision events.
This occurred in b18c8c8 (Thu May 17 2012).
This was a cause of very occasional race conditions and likely memory leakage as clients came and went from the region.
2012-07-11 22:58:09 +01:00
Justin Clark-Casey (justincc) f49c850269 If a link points to a non-existing item in FetchInventory caps, then don't try to add it to the return data rather than suffering an exception later on 2012-07-11 22:58:01 +01:00
Justin Clark-Casey (justincc) 70f85af75b Add IScene.Name for code clarity to replace the RegionInfo.RegionName used in many, many log messages. 2012-07-11 22:57:53 +01:00
Justin Clark-Casey (justincc) 663b0cc681 Change AttachmentsModule.DetachSingleAttachmentToInv() to accept a SOG directly instead of an item ID to then shuffle through attachments, saving CPU busywork.
Almost all callers already had the sog to hand.
Still checking that it's really an attachment, but now by inspecting SOG.AttachedAvatar
2012-07-11 22:57:39 +01:00
Justin Clark-Casey (justincc) 733a8c9f89 Rather than iterating through all SOGs in the scene looking for the one that matches out fromItemID on detach, go through the agent's attachment sog list instead. 2012-07-11 22:57:31 +01:00
Justin Clark-Casey (justincc) 25109c8e4d Remove code that tried to delete an attachment back to inventory if RezSingleAttachmentFromInventoryInternal() returned null.
null would only ever be returned if the item couldn't be located within inventory and this would happen immediately.
In this case, derezzing wouldn't work anyway since there is no item to derez.
2012-07-11 22:57:22 +01:00
Justin Clark-Casey (justincc) 51724128bf If rest of first line after colon is blank then still warn about running in XEngine if engine specified does not exist.
This is to take account of situations where the user was intending to specify a script engine using colon using its default language.
This probably generates few false positive as scripts are less likely to end a first line colon with a comment for other purposes.
2012-07-11 22:57:12 +01:00
Justin Clark-Casey (justincc) 461831a65e Avoid reporting false positives when a colon is in a comment in the first line of a script where the user was not trying to select a different script engine.
This works by only posting the "Selected engine unavailable" message if we're falling back on XEngine and the language is one handled by XEngine.
In cases where the language is not handled or not allowed, the user will still be notified by the later compiler error.
This avoids the overwhelming majority of false positives where the first line contains a : for other reasons (e.g. source control systems, vim settings, etc.)
Ultimately, I think it would be better to detect script language/engine with a mechanism that didn't just rely on : detection (e.g like #! in unix scripts).
2012-07-11 22:56:59 +01:00
Justin Clark-Casey (justincc) c6fa09c3af minor: reuse colon index calculation in XEngine.OnRezScript. The index if a colon is found on the first line will always be the same as for the whole script. 2012-07-11 22:56:45 +01:00
Justin Clark-Casey (justincc) 9ccf56eaae Fix issue in InventoryArchiveTestCase where it didn't call down to OpenSimTestCase.SetUp() 2012-06-27 21:52:23 +01:00
Justin Clark-Casey (justincc) ea9b0794e0 refactor: Move ScenePresence <-> AgentData attachments copying code into AttachmentsModule. 2012-06-27 21:52:16 +01:00
Justin Clark-Casey (justincc) 96191241be Automatically disable log4net before each regression test so that logging is confined to a single test if it's turned on.
This involves making test classes inherit from a common OpenSimTestCase.
This will be applied to more classes as required.
2012-06-27 21:52:08 +01:00
Justin Clark-Casey (justincc) 779f0ede49 Fix output for help on some object region console commands 2012-06-27 21:51:54 +01:00
Justin Clark-Casey (justincc) e511106d8d Show region positions in "show regions" robust console command 2012-06-27 21:51:48 +01:00
Justin Clark-Casey (justincc) 37f22e2946 minor: correct GridService "show regions" cibsike cinnabd usage statement 2012-06-27 21:51:40 +01:00
Justin Clark-Casey (justincc) b802906827 refactor: Remove unnecessary AttachmentModuleTests.m_userId in favour of local variables 2012-06-27 21:51:34 +01:00
Justin Clark-Casey (justincc) c6fb5f0fe4 refactor: Use local attachment module variables instead of global m_attMod.
This also avoids confusion between tests where one sets up m_attMod and another accidentally uses it after failing to set one up itself.
2012-06-27 21:51:27 +01:00
Justin Clark-Casey (justincc) 8909e70fc3 refactor: make m_presence a local variable in all AttachmentsModuleTests since it doesn't need to be global and some tests set up more than one sp 2012-06-27 21:51:19 +01:00
Justin Clark-Casey (justincc) 78fcee1f4b Add regression test to check that attachments in source region are deleting when an agent teleports to a neighbouring region 2012-06-27 21:51:12 +01:00
Justin Clark-Casey (justincc) 3106a0f25e If crossing attachments into another region pre-fatpack, clone objects before changing properties to avoid hud display race condition with update threads.
This matches behaviour in fatpack crossing, where attachments are cloned before their properties are changed.
This only applies to crossings to simulators running code released before April 2011.
2012-06-27 21:51:03 +01:00
Justin Clark-Casey (justincc) 19c2f08a8b Add much easier ConsoleDisplayTable AddColumn() and AddRow() methods.
Use these for new "show regions" command rather than old cumbersome stuff.
2012-06-27 21:50:52 +01:00
Justin Clark-Casey (justincc) 005ca12a99 Add "show regions" console command to ROBUST to show all regions currently registered.
Command is not added in standalone, which has its own version of "show regions" that can also show estate name
2012-06-27 21:50:44 +01:00
Justin Clark-Casey (justincc) 02fe1a676e Add "show region at" command to grid service to get the details of a region at a specific location. "show region" command becomes "show region name" to disambiguate
This is the same format as used by "show object name", etc.
"deregister region" also becomes "deregister region id"
2012-06-27 21:50:38 +01:00
Justin Clark-Casey (justincc) 03fc8cf155 minor: update currently commented out log message at top of AvatarFactoryModule.SetAppearance() for future use 2012-06-27 21:50:30 +01:00
Justin Clark-Casey (justincc) 8dedd91961 When attachments are being saved and deleted for a closing root agent, delete first to avoid a hud race condition with update threads.
If delete doesn't occur first then the update thread can outrace the IsAttachment = false necessary to save attachments and send hud artifacts to other viewers.
2012-06-27 21:50:22 +01:00
Justin Clark-Casey (justincc) 0ac040d9ca In AttachmentsModule.DetachSingleAttachmentToInvInternal(), remove attachment before changing properties for correct inventory serialization.
Serialization of attachments requires IsAttachment = false so that correct positions are serialized instead of avatar position.
However, doing this when a hud is still attached allows race conditions with update threads, resulting in hud artifacts on other viewers.
This change sets SOG.IsDeleted before serialization changes take place (IsDeleted itself is not a serialized property).
LLClientView then screens out any deleted SOGs before sending updates to viewers.
2012-06-27 21:50:09 +01:00
Justin Clark-Casey (justincc) c5e5308120 Resolve various race conditions between accessing and removing external script URLs by more consistently locking on m_UrlMap 2012-06-27 21:45:07 +01:00
Justin Clark-Casey (justincc) 1cfaacb88b Avoid a race condition where an incoming request to a script external URL can trigger an exception is the URL was being removed at the same time.
This involves three steps
1) Return gracefully in UrlModule.HttpRequestHandler() instead of throwing an exception when the url cannot be found in its index
2) Return true instead of false in HasEvents() if no matching request is found in the map.  This call will only happen in the first place for raced requests.
3) Return a 404 in GetEvents() if the request is not in the index, rather than a blank 200 OK.

Many thanks to Tom Haines in http://opensimulator.org/mantis/view.php?id=6051 for doing some of the work on this.
2012-06-27 21:45:00 +01:00
Justin Clark-Casey (justincc) 689cafec63 Avoid race condition between m_PrimObjects iteration in XEngine.PostObjectEvent and places where the list is modified by extending the m_PrimObjects lock. 2012-06-27 21:44:53 +01:00
Justin Clark-Casey (justincc) d4cd9e050b If starting scripts on initial sim start, provide INFO level log feedback each time 50 scripts have been started.
This is to provide an indication of what's happening now that the default isn't to report every single script start.
Changes XEngine logging level in OpenSim.exe.config from WARN to INFO.
2012-06-27 21:44:45 +01:00
Justin Clark-Casey (justincc) 472785a5e8 Eliminate unnecessary extra call to TriggerEmptyScriptCompileQueue in XEngine.DoOnRezScriptQueue()
The later invocation of this function will happen on an empty compile queue.
2012-06-27 21:44:38 +01:00
Justin Clark-Casey (justincc) da28fcd357 Stop flicking IsAttachment false and then true in AttachmentsModule.UpdateAttachmentPosition() in order to avoid a hud update race condition.
Previously, setting IsAttachment to false then true was necessary to serialize the updated attachment object information.
However, UpdateAttachmentPosition no longer does this update.
Whilst IsAttachment is set to false there is a race condition where the update thread can wrongly send hud object updates to clients that do not own the hud, resulting in screen artifacts.
2012-06-27 21:44:20 +01:00
Justin Clark-Casey (justincc) 1999338773 Fix bug where attachments would not retain position if just rotated and not moved.
This was because we were not setting AttachedPos in SOG.UpdateGroupPositionPR, unlike UpdateGroupPosition
2012-06-27 21:44:12 +01:00
Justin Clark-Casey (justincc) 95670d2086 refactor AttachmentsModule tests to use a common method for standard attachment item setup 2012-06-27 21:44:04 +01:00
Justin Clark-Casey (justincc) af2c48449c Add regression test for updating attachment position 2012-06-27 21:43:58 +01:00
Justin Clark-Casey (justincc) ffc6110edf Add item id, name, prim name and id to log message when state exists but loading fails.
Drop logging about memory limit exceeded to warn from error
2012-06-27 21:43:49 +01:00
Justin Clark-Casey (justincc) 1edd1f93c1 Retrigger build - last jenkins run was glitched 2012-06-27 21:41:49 +01:00
Justin Clark-Casey (justincc) b6e42da21a Add state file location to errors logged when there's some issue with retrieving state (e.g. exceeds memory limit) 2012-06-27 21:41:34 +01:00
Justin Clark-Casey (justincc) 2e0402433d Use HasPrivateAttachmentPoint properties in SOG.DeleteGroupFromScene() instead of magic numbers 2012-06-27 21:41:24 +01:00
Justin Clark-Casey (justincc) d19600e257 refactor: use SOG.HasPrivateAttachmentPoint in SOP.SendTerseUpdateToClient() instead of attachmentpoint magic numbers. 2012-06-27 21:41:15 +01:00
Justin Clark-Casey (justincc) a6d97e6353 As with LLSDInventoryItem from commit 01a2b0b, send type values in LLSDInventoryFolder for inventory CAPs as integers rather than strings.
Should also resolve some issues with exceptions being thrown in some inventory fetches.
2012-06-20 23:56:25 +01:00
Justin Clark-Casey (justincc) 8eb39eb3ac Lower warn logging on not having friends/group module on permissions to debug.
It's a valid configuration not to have these modules, but I think it's still worth logging the fact that certain permissions won't work (always return true)
2012-06-20 23:55:58 +01:00
Justin Clark-Casey (justincc) 553ac6335d minor: Lower flotsam asset cache warning about not having a FlotsamCache.ini to debug
It's perfectly okay not to have this section.
2012-06-20 23:55:51 +01:00
Justin Clark-Casey (justincc) 32a2515817 Change default logging level for XEngine to WARN instead of DEBUG.
This is to reduce log spam from script loading, which is especially spammy for avatar movements with scripted attachments.
All important messages are at warn or above.
If you still want/need to see these messages, set <level value="DEBUG"/> in the <logger name="OpenSim.Region.ScriptEngine.XEngine"> section of OpenSim.exe.config.
This affects no other package logs, which still output at the root configured level (currently DEBUG by default).
2012-06-20 23:55:42 +01:00
Justin Clark-Casey (justincc) a0482bccc7 Remove STARTUP COMPLETE message from the startuplogo.txt file and into main logging 2012-06-20 23:55:36 +01:00
Justin Clark-Casey (justincc) 3291e256ba Comment out the neighbour and land in connectors from info logging that they are starting up 2012-06-20 23:55:27 +01:00
Justin Clark-Casey (justincc) fb7573f713 Comment out recently added log message detailing number of scripts started when compile queue empties for now 2012-06-20 23:55:16 +01:00
Justin Clark-Casey (justincc) 4684207d6e Raise some IO associated Exception logging in XEngine to error level, in line with other similar cases.
Remove more unnecessary Close() calls - these are being triggered by the Dispose() called when exiting the using statement for these sdk io objects.
2012-06-20 23:55:09 +01:00
Justin Clark-Casey (justincc) 499b778391 Log how many scripts are candidates for starting and how many are actually started.
Adds DebugLevel infrastructure to XEngine though currently commented out and unused.
2012-06-20 23:54:16 +01:00
Justin Clark-Casey (justincc) 9779ceded5 If RegionReady is active, don't falsely say that logins are enabled in the main scene loop before RegionReady is signalled when initial script compilation finishes.
Also raises this logging level to Info from Debug since this information is of high importance.  This matches the behaviour of the RegionReady module
2012-06-20 23:44:28 +01:00
Justin Clark-Casey (justincc) 512d0ac411 minor: If logging because mesh/sculpt data isn't present for an object, log object UUID rather than local id, since UUID doesn't potentially vary between simulator starts. 2012-06-20 23:44:16 +01:00
Justin Clark-Casey (justincc) 981c7d63a0 Like the assembly and text files, only write the c#-lsl linemap in XEngine.SetXMLState() if the trust binaries flag is set.
This doesn't affect other locations where the map is written, such as on script compilation.
2012-06-20 23:44:03 +01:00
Justin Clark-Casey (justincc) 7bd1601a3f minor: Add a little more detail to IOException logging in XEngine.SetXMLState()
Also removes superflous Close() commands for statements taking place within using() constructs
Also adds some comment out debug log messages for future use.
2012-06-20 23:43:47 +01:00
Justin Clark-Casey (justincc) 3aef006e78 Change read config paramter from max_urls_per_simulator to max_external_urls_per_simulator, which is what it was meant to be 2012-06-20 23:33:54 +01:00
Justin Clark-Casey (justincc) 9a6aa528db Fix bug introduced in commit c6e3752 (13 Jun 2012) where poll responses would always return OK even if some other status code had been set 2012-06-20 23:33:46 +01:00
Justin Clark-Casey (justincc) 02a163848c Implement max_external_urls_per_simulator setting in [LL-Functions] to allow configuration of how many urls can be set up by llRequestURL()
Defaults remains as 100.
This setting is per simulator instead of per region due to how the url script module is structured.
2012-06-20 23:33:38 +01:00
Justin Clark-Casey (justincc) b9f122be07 Add region name to UseCircuitCode log messages 2012-06-20 23:33:27 +01:00
Justin Clark-Casey (justincc) e64ca361df Put all debug console commands into a single Debug section rather than scattering them over other categories 2012-06-20 23:33:13 +01:00
Justin Clark-Casey (justincc) 8a11c4e7d4 Make the "debug http" command available for robust as well as the simulator. This allows one to see incoming requests as they happen.
This required making everything use the common MainServer class for registering and retrieving http servers, rather than duplicate structures.
2012-06-20 23:33:04 +01:00
Justin Clark-Casey (justincc) 584a076bec Add main instance to internal MainServer.m_Servers list to simplify internal logic.
This does require the server to be added before it is set as the main Instance
2012-06-20 23:32:57 +01:00
Justin Clark-Casey (justincc) 88596d6097 minor: Tell user the current debug http level if "debug http" console command is executed without a level parameter 2012-06-20 23:32:44 +01:00
Justin Clark-Casey (justincc) 84d97b3bc0 When setting debug http level, do this for all known http servers, not just the main instance. 2012-06-20 23:32:38 +01:00
Justin Clark-Casey (justincc) 2b4e97eeaf Make XMLRPCModule use an existing HTTP server if one already exists on the desired port. 2012-06-20 23:32:30 +01:00
Justin Clark-Casey (justincc) a544280ef2 Get rid of some unnecessary null checks in RegionApplicationBase.StartupSpecific() - a constructor can never return null.
Also adds some method doc to MainServer
2012-06-20 23:32:23 +01:00
Justin Clark-Casey (justincc) 3a0f9836f3 minor: Extend 'debug http' usage statement to 0..3 from 0..2 2012-06-20 23:32:12 +01:00
Justin Clark-Casey (justincc) 4bfac5688d Shuffle "debug http" levels so that 1 and 2 now cause different levels of warn to be logged if we receive invalid xml for xmlrpc. 2012-06-20 23:32:06 +01:00
Justin Clark-Casey (justincc) 0fb93042c6 Fix a regression in BaseHttpServer.HandleXmlRpcRequests() from recent c6e3752
Accidentally make responseString null by default instead of String.Empty.
It needs to be something in case the XmlRpcRequest deserialize throws an exception due to bad xml (a failure which we silently swallow!)
2012-06-20 23:31:50 +01:00
Melanie a3586a7c4b Fix not sending TransferInfo when an asset is not found. This clogs
up the sound pipeline in the viewer.
2012-06-20 23:31:02 +01:00
Justin Clark-Casey (justincc) d4ff56710b Don't include time to transmit response back to requester when assessing slow handling of requests.
This is to avoid logging a 'slow' request when the source of delay is the viewer in processing a response.
This is not something we can do much about on the server end - it's server-side delay that we're interested in.
To ensure consistency, this commit also had to refactor and simplify inbound non-poll network request handling, though there should be no functional change.
IOSHttpResponse no longer exposes the Send() method, only classes in OpenSim.Framework.Servers.HttpServer should be doing this.
Only the GetTextureHandler was sending its own response.  Now it leaves this to BaseHttpServer, like all other core handlers.
2012-06-20 23:29:49 +01:00
Justin Clark-Casey (justincc) 6219c137e1 Fix very recent regression in 917d753 where I put the ++updatesThisCall outside the batching part of ProcessEntityUpdates()
This stopped any batching happening and since this method is called periodically updates were sent very slowly
2012-06-14 04:00:32 +01:00
Justin Clark-Casey (justincc) da3877a77d If we're going to discard a terse update block because it's now someone else's hud, then don't still add it to the list of blocks for the update message. 2012-06-14 04:00:22 +01:00
Justin Clark-Casey (justincc) 10ed7e3bbc correct wrong incomplete comment from previous commit 3c3ea19 in AttachmentsModule 2012-06-14 04:00:04 +01:00
Justin Clark-Casey (justincc) f248f8bf31 Fix a bug where scene objects attached as HUDs through scripts would not disappear for other avatars.
We do this by sending a kill message for that object to all other avatars apart from the one that has the hud.
2012-06-14 03:59:56 +01:00
Justin Clark-Casey (justincc) 6f2031001b Fix a race condition where an object update for a hud could be sent to non-owner avatars if the hud was attached directly from within the region.
If this happens, then the non-owners would see unremovable huds that they did not own until relog, and sometimes even beyond that.
This was due to a race between the entity update and the attachment code when moving an object from within scene to a hud.
2012-06-14 03:59:46 +01:00
Justin Clark-Casey (justincc) 1c5ad8e9ab Add SOG.HasPrivateAttachmentPoint to tell if a SOG has a private attachment point. HUDs attachment points are private.
Change SOP.SendFullUpdateToClient() and SoundModule.PlayAttachedSound() to use this rather than different magic number formulations.
This also corrects a bug in PlayAttachedSound() where the code assumed that all attachment points over 30 were HUDs.
It appears this is no longer true with Neck and Root (Avatar Center)
2012-06-14 03:59:39 +01:00
Justin Clark-Casey (justincc) d8d8b8fc9b minor: remove unnecessary IsAttachment = false setting for new object in UploadObjectAssetModule, property always starts as false 2012-06-14 03:59:09 +01:00
Justin Clark-Casey (justincc) 719efdaf1f minor: refactor part of LLClientView.ProcessEntityUpdates() to remove duplicate code 2012-06-14 03:58:54 +01:00
Justin Clark-Casey (justincc) 6a8e3907ca Remove long obsolete and unused IClientAPI.KillEndDone() 2012-06-14 03:18:23 +01:00
Justin Clark-Casey (justincc) 5a1b8fc6f7 Add ObjectUpdate as one of the packets that can be screened out when setting debug packet level 2012-06-14 03:18:15 +01:00
Justin Clark-Casey (justincc) 00ac962db7 In the osGetGrid functions, if the [GridInfo] section does not exist then return "Configuration Error", as already happens if there is no GridInfoURI 2012-06-14 03:18:08 +01:00
Justin Clark-Casey (justincc) cb518ad68c Add "deregister region" by uuid command to grid service to allow manual deregistration of simulators.
Useful if a simulator has crashed without removing its regions and those regions have been reconfigured differently
2012-06-14 03:18:00 +01:00
Justin Clark-Casey (justincc) 4859bc8c49 Remove accidental timeout left in during earlier debugging. Has been in since two commits ago (b099f26) 2012-06-14 03:13:55 +01:00
Justin Clark-Casey (justincc) 196e014782 OnConnectionClosed listeners, retrieve data from IClientAPI.SceneAgent rather than scanning all scene for the presence with the right id
Stop checking IsLoggingOut on these listeners, if called with a root agent then we always want to perform these actions.
This covers cases where the client is closed due to manual kick, simulator shutdown, etc.
2012-06-14 03:13:37 +01:00
Justin Clark-Casey (justincc) c6ffaaa959 Set IClientAPI.IsActive = false early on client removal due to ack timeout rather than using IsLoggingOut flag.
IsActive is more appropriate since unack timeout is not due to voluntary logout.
This is in line with operations such as manual kick that do not set the IsLoggingOut flag.
It's also slightly better race-wise since it reduces the chance of this operation clashing with another reason for client deactivation (e.g. manual kick).
2012-06-14 03:08:08 +01:00
Justin Clark-Casey (justincc) c3104f4bd2 If the simulator closes a root agent due to ack timeout, then send the client a kick message with that reason, in case it is somehow still listening. 2012-06-14 03:07:32 +01:00
Justin Clark-Casey (justincc) d8c40ca462 In PresenceDetector.OnConnectionClose(), use the IsChildAgent check already available on IClientAPI.SceneAgent rather than retrieving it again by scanning all scenes. 2012-06-14 03:07:25 +01:00
Justin Clark-Casey (justincc) 48f47bb4c7 Comment out the scene presence sitting debug log messages for now 2012-06-14 03:04:09 +01:00
Justin Clark-Casey (justincc) 8db6edbe87 Set CreateDefaultAvatarEntries = true in Robust.HG.ini.example to match Robust.HG.ini
Thanks to Ai Austin for the spot.
2012-06-14 03:04:02 +01:00
Justin Clark-Casey (justincc) a57b78b44b Scale down per frame MS stats to match scaled simulator FPS stat.
This makes frame time stats properly tally with fps, which saves confusion and makes it easier to interpret numbers.
In some ways this is not so artifical - physics FPS runs at the higher rate.
2012-06-14 03:03:26 +01:00
Justin Clark-Casey (justincc) 280d005d55 Start sending spare frame time MS viewer stat. Make frame time correctly display total frame time, not just non-spare time.
This makes it easier to see when components of frame time exceed normal permitted frame time.
Currently reflect scene frame times.
2012-06-14 03:03:01 +01:00
Justin Clark-Casey (justincc) 61e7d4a0e2 Properly show per frame millisecond statistics per frame, not as amount of time taken per second.
This is to make these statistics actually match their names (and also be more accurate as number of frames can vary under heavy load)
Currently using scene frames (11.23 every second) instead of physics frames (56.18 per second)
2012-06-14 02:51:43 +01:00
Justin Clark-Casey (justincc) 3e75083d2d Add last frame time monitor to MonitorModule now that this value is useful 2012-06-14 02:51:17 +01:00
Justin Clark-Casey (justincc) 3d400dd677 Create avatar entries necessary to stop new v3 avatars being clouds (pants, shape, etc.) by default in grid mode.
This only affects avatars created through the "create user" console command or createuser XMLRPC.
This matches the default setting for standalone
2012-06-14 02:50:59 +01:00
Justin Clark-Casey (justincc) 1fbb0f97bf Add documentation to AllowGodFunctions setting in [LL-Functions] 2012-06-14 02:50:43 +01:00
Justin Clark-Casey (justincc) 4968191c1e Fix regression in 5f4f9f0 (Fri Jun 8 2012) which stopped "show stats" and json stats from working 2012-06-14 02:50:36 +01:00
Justin Clark-Casey (justincc) 8889309324 Stop sending a DisableSimulator packet in LLClientView.Close(), which is a duplicate for child agents and unnecessary for root agents.
Close() already calls Scene.RemoveClient() which sends the right eq or udp DisableSimulator message to child agents.
2012-06-14 02:50:28 +01:00
Justin Clark-Casey (justincc) 27a7ba3e6a Instead of retrieving the known client again in LLUDPServer.RemoveClient(), check the IsLoggingOut flag instead.
This is slightly better thread-race wise
2012-06-14 02:50:17 +01:00
Justin Clark-Casey (justincc) 2d16d14ef1 If logging a client out due to ack timeout, do this asynchronously rather than synchronously on the outgoing packet loop.
This is the same async behaviour as normal logouts.
This is necessary because the event queue will sleep the thread for 5 seconds on an ack timeout logout as the client isn't around to pick up the final event queue messages.
2012-06-14 02:50:09 +01:00
Justin Clark-Casey (justincc) f2f8dcd65c Add regression test for client logout due to ack timeout. 2012-06-14 02:50:02 +01:00
Justin Clark-Casey (justincc) 332f8b6623 Remove null checks at top of LLUDPServer.ProcessInPacket(). Neither packet nor client are ever null. 2012-06-14 02:49:55 +01:00
Justin Clark-Casey (justincc) 4eda679e12 Store already retrieve IClientAPI in IncomingPacket structure for later use rather than doing another retrieve on dequeue.
Instead of checking whether the client still exists by trying to retrieve again from the client manager, this patch gets it back from IncomingPacket and checks the IClientAPI.IsActive state.
2012-06-14 02:49:39 +01:00
Justin Clark-Casey (justincc) 498154af80 Don't make duplicate call to ScenePresence.Close() separately in ETM.DoTeleport() if an agent needs closing.
This is always done as part of Scene.RemoveClient()
Also refactors try/catching in Scene.RemoveClient() to log NREs instead of silently discarding, since these are useful symptoms of problems.
2012-06-14 02:49:31 +01:00
Justin Clark-Casey (justincc) ba0ebe6d75 Go back to calling IncomingCloseAgent() in the "kick user" command for consistency instead of IClientAPI.Close() directly.
This no longer double counts child agent removals
2012-06-14 02:49:22 +01:00
Justin Clark-Casey (justincc) 28f93512bc Remove duplicate update of user count in Scene.IncomingCloseAgent()
This is already done in Scene.RemoveClient() which IncomingCloseAgent() always ends up calling.
2012-06-14 02:49:14 +01:00
Justin Clark-Casey (justincc) 78c2ef2346 Fix bug with "kick user" reducing agent counts by 2 instead of 1.
This is done by making the kick user command call IClientAPI.Close() rather than routing through Scene.IncomingCloseAgent(), which also called IClientAPI.Close()
DisableSimulator for child agents is moved from IncomingCloseAgent() to RemoveClient(), this is not a functional change since IncomingCloseAgent() always ends up calling RemoveClient()
2012-06-14 02:49:05 +01:00
Justin Clark-Casey (justincc) d30d68657e Record the fact that child agents can have asset transactions.
Also change code to grab the agent asset transaction module once.
2012-06-14 02:48:56 +01:00
Justin Clark-Casey (justincc) 3a27f656b3 Don't send kill object messages to clients when a child agent is closed. 2012-06-14 02:48:48 +01:00
Justin Clark-Casey (justincc) cc27a6cb84 Log warning if we try to remove a UDP client that has already been removed. 2012-06-14 02:48:36 +01:00
Justin Clark-Casey (justincc) ed21576ce0 Allow the thread watchdog to accept an alarm method that is invoked if the timeout is breached.
This alarm can then invoke this to log extra information.
This is used in LLUDPServer to show which client was being processed when incoming and outgoing udp watchdog alarms are triggered.
2012-06-14 02:48:29 +01:00
Talun 9d9e042b4c Mantis 4597 AgentPaused packet is ignored.
The packet was actually being handled but not acted on.
This change extends the default timeout for paused clients to 5 minutes
and makes both the paused and non-paused timeout periods configurable.
2012-06-14 02:47:21 +01:00
Justin Clark-Casey (justincc) 4fb8d5cfba Remove unused ScenePresence list structure in llGetAgentList() 2012-06-06 01:40:45 +01:00
Justin Clark-Casey (justincc) 896c4b6248 Fix build break whree accidentally did inv.Folders rather than inv.Folders.Count in a minor change. 2012-06-04 21:17:43 +01:00
Justin Clark-Casey (justincc) f6730da13a minor: tidy up some comments 2012-06-04 21:17:23 +01:00
Justin Clark-Casey (justincc) 41d98916df Fix various issues with http inventory
1) The return messages were being wrongly populated with the names of asset, inventory and sale types when their corresponding integers should have been used instead.
2) Folders with links were including the linked items in the descendents figure, when only the links should be included.
3) Links and linked items in link folders were not being included in the return data, and not in the correct order.

Now that these issues have been addressed, outfits and attachments appear to work consistently when HTTP inventory is enabled (as is now the default).
2012-06-04 21:17:15 +01:00
Justin Clark-Casey (justincc) 771539a4e0 Instead of updating sim stats root agent, child, objects and scripts accounts every single scene frame, update in the once every 3 seconds SimStatsReporter run 2012-06-04 21:16:46 +01:00
Justin Clark-Casey (justincc) 27c62bba99 Add optional total avatars, total prims and active prims stats to ODE plugin.
These will act as a sanity check with the main scene stats, to show that physics scene entities are being managed properly.
Total prims will not match scene total prims since physics total does not include phantom prims
2012-06-04 21:08:28 +01:00
Justin Clark-Casey (justincc) 93e053a122 If OdeScene.Near() returns no collision contacts, then exit as early as possible. All subsequent code is only relevant if there are contacts. 2012-06-04 21:08:21 +01:00
Justin Clark-Casey (justincc) eb022f4cc1 Add optional stat for the other collision time per frame not spent in ODE native spaces or geom collision code 2012-06-04 21:08:12 +01:00
Justin Clark-Casey (justincc) 83542034dd Add avatar forces calculation, prim force and raycasting per frame millisecond optional stats 2012-06-04 21:08:02 +01:00
Justin Clark-Casey (justincc) 627382f702 Collection optional avatar and prim taint frame millisecond times 2012-06-04 21:07:51 +01:00
Justin Clark-Casey (justincc) 2eb563b3bb Remove recent optional native collision frame milliseconds stat
Unnecessary since this has now been broken down into space collisions and geom collisions
2012-06-04 21:07:41 +01:00
Justin Clark-Casey (justincc) 54a23f14d5 Add optional stat that records milliseconds spent notifying collision listeners in physics frames 2012-06-04 21:07:32 +01:00
Justin Clark-Casey (justincc) e8059b74f8 Add avatar and prim update milliseconds per frame optional stats 2012-06-04 21:07:23 +01:00
Justin Clark-Casey (justincc) 075909520a Add option native step frame ms stat 2012-06-04 21:07:16 +01:00
Justin Clark-Casey (justincc) 808bf12cd5 Add total ODE frame time optional stat, as a sanity check on the main scene physics stat 2012-06-04 21:07:07 +01:00
Justin Clark-Casey (justincc) 0f39f41317 Break down native ODE collision frame time stat into native space collision and geom collision stats 2012-06-04 21:07:00 +01:00
Justin Clark-Casey (justincc) f23b7ae3e9 Rename new collision stats to 'contacts' - there are/can be multiple contacts per collision and this is what is actually being measured. 2012-06-04 21:06:52 +01:00
Justin Clark-Casey (justincc) 5e4b09fc22 Stop adding an unnecessary duplicate _perloopcontact if the avatar is standing on a prim.
This has already been added earlier on in the method.
2012-06-04 21:06:42 +01:00
Justin Clark-Casey (justincc) 25ab7841b7 minor: comment out currently unused OdeScene.sCollisionData 2012-06-04 21:06:32 +01:00
Justin Clark-Casey (justincc) 0c0e575379 Add ODE avatar and prim collision numbers if extra stats collection is enabled. 2012-06-04 21:06:23 +01:00
Justin Clark-Casey (justincc) 68946bffae Fix OdeScene.GetTopColliders() to return the top 25 colliders rather than the first 25 that had non-zero collision scores.
Also zeros collisions scores on all prims after report collection, not just the top 25.
As before, this collision scores are only reset after a report is requested, which may give unrealistic numbers on the first request.
So to see more realistic scores, ignore the first report and then refresh the request after a couple of seconds or so.
2012-06-04 21:06:13 +01:00
Justin Clark-Casey (justincc) 2fc461d9ab Add an optional mechanism for physics modules to collect and return arbitrary stats.
If active, the physics module can return arbitrary stat counters that can be seen via the MonitoringModule
(http://opensimulator.org/wiki/Monitoring_Module)
This is only active in OdeScene if collect_stats = true in [ODEPhysicsSettings].
This patch allows OdeScene to collect elapsed time information for calls to the ODE native collision methods to assess what proportion of time this takes compared to total physics processing.
This data is returned as ODENativeCollisionFrameMS in the monitoring module, updated every 3 seconds.
The performance effect of collecting stats is probably extremely minor, dwarfed by the rest of the physics code.
2012-06-04 21:05:57 +01:00
Justin Clark-Casey (justincc) 59a48d9ebb Add console command "teleport user" to allow teleport from the region console
See "help teleport user" on the console for more details
2012-05-31 02:28:30 +01:00
Justin Clark-Casey (justincc) 533d1ea20c refactor: factor out entity transfer state machine into a separate class to make code more analyzable 2012-05-31 02:28:20 +01:00
Justin Clark-Casey (justincc) dca1ca1d07 If handling the failure of teleport, move agent state to CleaningUp when we start the handling.
Also fixes the log warning from ResetInTransit() if the state is cleared direct from Transferring or ReceiveAtDestination, as pointed out in mantis 5426
2012-05-31 02:25:07 +01:00
Justin Clark-Casey (justincc) 20a3907e86 If restating a region, clean up the physics scene after the main scene has been closed not before.
If this is done before then on ODE agent update calls still incoming can fail as they try to use a raycastmanager that has been disposed.
Bullet plugin does nothing on Dispose()
However, I wouldn't be at all surprised if individual region restarting was buggy in lots of other areas.
2012-05-31 02:24:36 +01:00
Justin Clark-Casey (justincc) 7358e5748d Add Blake/Techplex to CONTRIBUTORS. Thanks! 2012-05-31 02:24:31 +01:00
Blake.Bourque a1b64db942 One can now get hyoergrid region co-ordinates with llRequestSimulatorData 2012-05-31 02:23:00 +01:00
Justin Clark-Casey (justincc) 4d44f2d248 Use GetInventoryItem() in LSL_Api.InventoryKey(string name, int type).
Also removes small bug where calling this method would add 1 to LPS, evne though all callers already did this.
2012-05-31 02:22:53 +01:00
Justin Clark-Casey (justincc) 67abbcf269 Use SceneObjectPartInventory.GetInventoryItem() in OSSL.AvatarStopAnimation instead of searching the task inventory manually. 2012-05-31 02:22:45 +01:00
Justin Clark-Casey (justincc) 6b819a9032 refactor: replace LSL_Api.InventoryKey(string) largely with SceneObjectPartInventory.GetInventoryItem(string)
Also gets llStopAnimation() to call KeyOrName rather than duplicating logic.
2012-05-31 02:22:27 +01:00
Talun 2021a8aedb Mantis 6028 osAvatarStopAnimation not stopping animations via UUID
Corrected to stop animations using the animation UUID similar to llStopAnimation.
See http://opensimulator.org/wiki/OsAvatarStopAnimation
2012-05-31 02:18:55 +01:00
Justin Clark-Casey (justincc) 58dc175ae3 on agent cross, remove from physics scene after its been placed in transit, not before. 2012-05-31 02:18:27 +01:00
Justin Clark-Casey (justincc) 4ad6763956 refactor: make ETM.CrossAgentToNewRegionAsync neighbourRegion == null check return earlier to simplify method 2012-05-31 02:18:20 +01:00
Justin Clark-Casey (justincc) 702826b850 Fix bug where a failed QueryAccess to a remove region would always have the reason "Communications failure" no matter what the destination region actually returned 2012-05-31 02:18:11 +01:00
Justin Clark-Casey (justincc) 8d30a1f74b Stop it being possible for an agent to teleport back to its source region before the source region has finished cleaning up old agent data and structures.
If this is allowed, then the client usually gets forcibly logged out and data structures might be put into bad states.
To prevent this, the binary state machine of EMT.m_agentsInTransit is replaced with a 4 state machine (Preparing, Transferring, ReceivedAtDestination, CleaningUp).
This is necessary because the source region needs to know when the destination region has received the user but a teleport back cannot happen until the source region has cleaned up.
Tested on standalone, grid and with v1 and v3 clients.
2012-05-31 02:18:03 +01:00
Justin Clark-Casey (justincc) 1a988ba835 In remote QueryAccess, also receive the actual status (true|false) instead of always true no matter what the callee actually returned.
This was due to two things
1) SimulationServiceConnector.QueryAccess was always looking to the outer result["success"].
But if a "_Result" map is returned (which is certainly the case right now), then the true success is _Result["success"], result["success"] is always true no matter what
2) If QueryAccess was false at the destination, then AgentHandlers.DoQueryAccess() was never putting this in the result.
The default action of SerializeJsonString() is not to put false booleans in the JSON!!!, so this has to be explicitly set.
2012-05-31 02:17:55 +01:00
Justin Clark-Casey (justincc) c422f852a6 Don't actually proceed on a within-region teleport if another is already taking place, rather than just (falsely) logging that we're not going to proceed.
An oversight from recent commit 9ab0c81
2012-05-31 02:17:49 +01:00
Justin Clark-Casey (justincc) bcacdb3352 On inter-region teleport, only stand the avatar up if the QueryAccess call to the destination scene actually succeeds. 2012-05-31 02:17:42 +01:00
Justin Clark-Casey (justincc) cd61567de8 Now that the EntityTransferModule is per-region, fetch the event queue module once rather than repeatedly via scene presences 2012-05-31 02:17:35 +01:00
Justin Clark-Casey (justincc) 5c48c3c57a Fix issue where a dns resolution failure on the final destination might leave the user unable to teleport since the transit flag was not being reset.
This moves the 'already in transit' check further up and resets the flag if dns resolution fails and in the new required places.
2012-05-31 02:17:28 +01:00
Justin Clark-Casey (justincc) 7692ccc0cc Make ISimulationScene.GetScene() used the more efficient region id for lookup rather than the region handle. 2012-05-31 02:17:18 +01:00
Justin Clark-Casey (justincc) 17cc7e85e2 If an agent is still registered as 'in transit' by the source region, don't allow an immediate teleport back.
This is to help relieve a race condition when an agent teleports then immediately attempts to teleport back before the source region has properly cleaned up/demoted the old ScenePresence.
This is rare in viewers but much more possible via scripting or region module.
However, more needs to be done since virtually all clean up happens after the transit flag is cleared .
Possibly need to add a 'cleaning up' state to in transit.
This change required making the EntityTransferModule and HGEntityTransferModule per-region rather than shared, in order to allow separate transit lists.
Changes were also required in LocalSimulationConnector.
Tested in standalone, grid and with local and remote region crossings with attachments.
2012-05-31 02:16:52 +01:00
Justin Clark-Casey (justincc) 96b3e1d0fa Don't eagerly clear frame collision events when physics actors subscribe and unsubscribe from collisions, in order to avoid a race condition.
Since this is done directly from ScenePresence, it can lead to a race condition with the simulator loop.
There's no real point doing it anyway since the clear will be done very shortly afterwards by the simulate loop and either there are no events (for a new avatar) or events don't matter (for a departing avatar).
This matches existing behaviour in OdePrim
2012-05-31 02:11:45 +01:00
Justin Clark-Casey (justincc) dc3cfcbe69 Check agent limit against root agent count rather than both root and child agents
From sl docs such as http://community.secondlife.com/t5/English-Knowledge-Base/Managing-Private-Regions/ta-p/700115
agent should apply to avatars only.
This makes sense from a user perspective, and also from a code perspective since child agents with no physics or actions take up a fraction of root agent resources.
As such, the check is now only performed in Scene.QueryAccess() - cross and teleport check this before allowing an agent to translocate.
This also removes an off-by-one error that could occur in certain circumstances on teleport when a new child agent was double counted when a pre-teleport agent update was performed.
This does not affect an existing bug where limits or other QueryAccess() checks are not applied to avatars logging directly into a region.
2012-05-31 02:05:59 +01:00
Justin Clark-Casey (justincc) 1ca1f80eac Remove a call stack debugging line accidentally left in from a few days ago at SceneObjectPartInventory.ApplyNextOwnerPermissions(). 2012-05-25 02:56:06 +01:00
Justin Clark-Casey (justincc) afe2b437bc minor: Change [OBJECT COMMANDS MODULE] log strings to [REGION COMMANDS MODULE] strings, though all these are currently commented out anyway 2012-05-24 01:24:24 +01:00
Justin Clark-Casey (justincc) dff71c1aa9 Add "show scene" command which lists stats for the currently selected console scene(s)
This includes prim count, script count, avatar count, etc.
Information is currently the same as "show stats", though show stats can only show one scene at a time because it listens for the latest outgoing stats packet (a bad approach that needs to change).
Might be better to tie this module into the other stats module to display arbitrary stats rather than fetching directly from scene.SimStatsReporter.
Console command is "show scene" because "show region" already exists for the grid service, which is unfortunate.
Might need to make a distinction between "scene" relating to a live scene and "region" relating to more static region data (url, coords, etc.)
2012-05-24 01:24:12 +01:00
Justin Clark-Casey (justincc) 7f9a025e30 refactor: Rename ConsoleTableRow and ConsoleTableColumn to ConsoleDisplayTableRow and ConsoleDisplayTableColumn 2012-05-24 01:24:06 +01:00
Justin Clark-Casey (justincc) a0ac284a11 Add ConsoleDisplayList for more consistent formatting of console output in list form.
Convert "show region" to use this structure rather than hand-constructing
2012-05-24 01:23:57 +01:00
Justin Clark-Casey (justincc) 5341036261 refactor: rename ConsoleTable -> ConsoleDisplayTable for clarity 2012-05-24 01:23:50 +01:00
Justin Clark-Casey (justincc) 46a6cab307 Add missing Y co-ord in "show region" console command information 2012-05-24 01:23:43 +01:00
Justin Clark-Casey (justincc) edb17d1aac Lay out "show region" information in an easier to read line by line format 2012-05-24 01:23:34 +01:00
Justin Clark-Casey (justincc) dd05e96066 Fetch the dialog module reference in AttachmentsModule in RegionLoaded() not AddRegion()
The reference is not guaranteed to be there when AddRegion() is called but will definitely be present at RegionLoaded() if it's going to be present at all.
2012-05-24 01:23:27 +01:00
Justin Clark-Casey (justincc) ed0878ca23 minor: Make log class names in InventoryAccessModule uniform 2012-05-24 01:23:20 +01:00
Justin Clark-Casey (justincc) 54c222be26 Fix bug where an avatar that had an object they owned attached through llAttachToAvatar() or osForceAttachToAvatar() would wrongly have next permissions come into play when they detached that object and rezzed it in scene.
This is because the attachments module code was setting the 'object slam' bit by using PermissionMask.All
Solution here is to route the attachment item creation call through the existing inventory code in BasicInventoryAccessModule rather than copy/pasted code in AttachmentsModule itself.
2012-05-24 01:23:09 +01:00
Justin Clark-Casey (justincc) 80d139297a Setting 'in transit' on a local teleport as well as inter-region teleports.
This is to eliminate possible race conditions if two teleport calls are made concurrently, where at least one is a local teleport.
This is pretty much impossible on a manual user teleport but can happen on script-invoked teleports.
2012-05-24 01:23:03 +01:00
Justin Clark-Casey (justincc) 8e6459f616 minor: extend commented out LinkInventoryItem log message for future use 2012-05-24 01:22:48 +01:00
Justin Clark-Casey (justincc) ba909cb692 Fix bug where outfit folders could not be renamed.
Outfit folders are a type of system folder whose details are allowed to change.
2012-05-24 01:19:53 +01:00
Justin Clark-Casey (justincc) 96b964f7fa Enable FetchInventoryDescendents2 and FetchInventory2 caps by default. This appears to be required now for LL 3.3.1 to work properly.
Without this, LL 3.3.1 continually pushes LLInventoryModelFetchDescendentsResponder::error 499 to its log.
This cap will be ignored by older viewers - UDP inventory will work normally.
2012-05-24 01:15:04 +01:00
Justin Clark-Casey (justincc) 7bbab2f1d5 Fix issue where a new outfit folder is not created when a new outfit is saved if there are no previous outfits
This was because AddFolder() was disallowing these though they are legal.
2012-05-24 01:14:44 +01:00
Justin Clark-Casey (justincc) e5f3af4abe Fix build break. Comment out EQG deregister/register logging. 2012-05-24 01:10:33 +01:00
Justin Clark-Casey (justincc) 452538c6b0 Add millisecond logging to pCampBot for debugging purposes 2012-05-24 01:10:24 +01:00
Justin Clark-Casey (justincc) 5c828724f3 Add level 2 debug eq logging which logs event queue polls.
Refactor: eq message logging into common method.
2012-05-24 01:10:15 +01:00
Justin Clark-Casey (justincc) 6538dd24bb Invoke log4net configurator in pCampBot.exe in order to get OpenSim sylte logging 2012-05-24 01:10:09 +01:00
Justin Clark-Casey (justincc) 996abe1ea5 refactor: move EventQueueGet path generation into common method. Rename some local variables in line with code conventions. Add commented out EQG log lines for future use. 2012-05-24 01:09:58 +01:00
Justin Clark-Casey (justincc) f421e0c3d1 Don't eagerly clear frame collision events when physics actors subscribe and unsubscribe from collisions, in order to avoid a race condition.
Since this is done directly from ScenePresence, it can lead to a race condition with the simulator loop.
There's no real point doing it anyway since the clear will be done very shortly afterwards by the simulate loop and either there are no events (for a new avatar) or events don't matter (for a departing avatar).
This matches existing behaviour in OdePrim
2012-05-24 01:09:46 +01:00
Justin Clark-Casey (justincc) e4eaca5f9b minor: improve method doc for TestSameSimulatorSeparatedRegionsCreateAgentFails() 2012-05-24 01:08:32 +01:00
Justin Clark-Casey (justincc) ef5925fa18 Add regression TestSameSimulatorSeparatedRegionsCreateAgentFails() 2012-05-24 01:08:30 +01:00
Justin Clark-Casey (justincc) bae48a9394 minor: Remove redundant EstateOwner != UUID.Zero check in IsAdministrator because checking EstateOwner == user
Due to an earlier check we already know that user != UUID.Zero so if EstateOwner == UUID.Zero, EstateOwner == user can never be true
2012-05-24 01:06:47 +01:00
Justin Clark-Casey (justincc) c813ed44d8 Comment out TestSameSimulatorSeparatedRegionsQueryAccessFails() regression test logging accidentally left in 2012-05-17 01:52:15 +01:00
Justin Clark-Casey (justincc) 885bec68bd Add regression TestSameSimulatorSeparatedRegionsQueryAccessFails() 2012-05-17 01:52:06 +01:00
Justin Clark-Casey (justincc) b553a05db3 Remove redundant "Teleport failed:" from reason when QueryAccess fails for the destination simulator. This part of the string is already provided by the viewer.
Also adds more reason logging for diagnostics when teleports are refused/fail.
2012-05-17 01:51:59 +01:00
Justin Clark-Casey (justincc) 5473c4f8cc Route OAR SOG loading through the common SceneObjectSerializer.FromXml2Format() rather than the functionally identical but buggy Xml2ToSOG().
Remove buggy Xml2ToSOG().
2012-05-17 01:51:48 +01:00
Justin Clark-Casey (justincc) 0d73f81fb5 Fix issue where loading OARs could sometimes result in link numbers being reordered.
This was because the parts in scene objects were sometimes not serialized in link order.
This is perfectly fine since the parts still have the right link numbers, but an extra fix to adjust for this
had not been done in the SerialiserModule methods that OAR loading used.
Add regression test for same.
Addresses http://opensimulator.org/mantis/view.php?id=5948, http://opensimulator.org/mantis/view.php?id=5749
2012-05-17 01:51:39 +01:00
Justin Clark-Casey (justincc) 66c204b983 Allow use of regular expressions in "show object name", "show part name" and "delete object name" console commands if --regex switch is used.
Deleteing objects by name, creator uuid or owner uuid now requires confirmation to avoid accidental deletion.
2012-05-17 01:51:32 +01:00
Justin Clark-Casey (justincc) afb0600621 minor: add explanative comment to 'missing baked texture' logging commonly seen on inter-simulator teleports where avatar baked textures are not available from the asset service. 2012-05-17 01:50:52 +01:00
Justin Clark-Casey (justincc) a13f2c6985 minor: comment out individual attachment transfer log messages for now 2012-05-17 01:50:45 +01:00
Justin Clark-Casey (justincc) 17c7ef06ba Set the agent in transit teleport flag at the first available opportunity (i.e. when IsInTransit() was being checked) to close down a race condition.
On EntityTransferModule.DoTeleport() there was an IsInTransit() check to prevent multiple simultaneous teleport attempts.
However, the SetInTransit() was only performed later on, which left a window in which multiple threads could pass the IsInTransit() check.
This has been seen in the field and the results aren't pretty.
This commit effectively combines the IsInTransit() and SetInTransit() checks so there is no such window.
More failure cases are made to to call ResetInTransit() to adjust to this move.
2012-05-17 01:50:35 +01:00
Justin Clark-Casey (justincc) 4933ce49b6 Add more region information to some teleport related logging 2012-05-17 01:50:27 +01:00
Justin Clark-Casey (justincc) 5cec1fa50a Fix mono compiler warning.
Last jenkins failure looked like a glitch.
2012-05-17 01:50:14 +01:00
Justin Clark-Casey (justincc) debd83b06a Print out more information on connecting bots 2012-05-17 01:50:02 +01:00
Justin Clark-Casey (justincc) f01618ad1a Stagger multiple bot logins by 5 seconds to make this part of the test more 'realistic'
TODO: Need to make this value configurable by a command line parameter to pCampbot
2012-05-17 01:49:48 +01:00
Justin Clark-Casey (justincc) cfc1dba99b Do bot startup on another thread so console is responsive during this process 2012-05-17 01:49:39 +01:00
Justin Clark-Casey (justincc) 529a3f2400 Do each bot shutdown on its own threads to prevent one slow shutdown holding up all the rest.
This does increase the aggressiveness of shutdown
Also prevents the bot list being locked for a long period, which was preventing commands such as "show bots" from working during shutdown
2012-05-17 01:49:31 +01:00
Justin Clark-Casey (justincc) 7c1abc5225 Increase minimum period between bot actions to 3 seconds, so that teleport doesn't fall under the minimum 2 second limits that clients take to process it 2012-05-17 01:49:15 +01:00
Justin Clark-Casey (justincc) ca22b5e2f0 Change bot.IsConnected to be ConnectionState with Disconnected, Connecting, Connnected and Disconnecting states 2012-05-17 01:48:47 +01:00
Justin Clark-Casey (justincc) 9ec74f2098 Provide feedback on bot login states in pCampbot 2012-05-17 01:48:45 +01:00
Justin Clark-Casey (justincc) cb4ae39cb9 If a bot is not connected, show region name "(none)" instead of throwing an exception in the "show bots" command of pCampbot 2012-05-17 01:46:55 +01:00
Justin Clark-Casey (justincc) 802488814f Add ConsoleTable framework class for future uniform formatting of console output tables.
Still subject to change - if you use this be prepared to change your output code if/when the methods change.
Make new "attachments show" command use this.
2012-05-17 01:46:46 +01:00
Justin Clark-Casey (justincc) 53aa48b42c Add "attachments" show console command that will show the server's record of which attachments an in-scene avatar has.
For debugging purposes.
2012-05-17 01:46:36 +01:00
Justin Clark-Casey (justincc) b33801f854 Improve logging on the prim inventory script asset request path for future use.
This adds name and description of the request handler to http request logging when DebugLevel >= 1
2012-05-17 01:45:51 +01:00
Talun fc88ce0615 Mantis 6015 new LSL function llGetAgentList.
Details in the lsl wiki
2012-05-17 01:45:43 +01:00
Justin Clark-Casey (justincc) 28daec7f4e Remove physics actor related race conditions in SetVehicleFlags() and SetPhysicsAxisRotation()
sop.PhysActor can currently become null at any time.
2012-05-17 01:45:35 +01:00
Justin Clark-Casey (justincc) f25efa291d Add automated TestllBreakLink() 2012-05-17 01:45:24 +01:00
Justin Clark-Casey (justincc) 5ed0559cf2 Add automated TestllCreateLink() 2012-05-17 01:45:13 +01:00
Justin Clark-Casey (justincc) 8c1e549c12 refactor: Eliminate local id parameter from api initialize.
This is always available from m_host.LocalId
2012-05-17 01:44:59 +01:00
Justin Clark-Casey (justincc) 796334c5ff Instead of constantly looking up unchanging self item in script code, pass in self item on initialization. 2012-05-17 01:44:21 +01:00
Justin Clark-Casey (justincc) 2e1c2e1261 Escape and unescape xml element names if necessary in ServerUtils.BuildXmlData() and ParseElement()
If AvatarService appearance data is retrieved over the network, then ServerUtils was attempting to transfer names such as "Wearable 0:0" directly to xml element names, resulting in an exception.
Space is not valid in xml element names.  Neither is : in this case since the intention is not to namespace.  Using names directly as keys is not a good idea.
To get around this problem this patch escapes and unescapes the element names as appropriate.
This has no impact on existing xml (since it had to be valid in the first place) but allows AvatarService data to be used over the network.
Setting appearance (from simulator to AvatarService) did not suffer this problem since the values are passed in the query string which is already properly escaped.
2012-05-10 00:50:20 +01:00
Talun a896aac4bd Mantis 1456 same region teleport of a sitting avatar.
Region to region was fixed some time ago in EntityTransferModule.
This applies the same fix for same region teleports.
2012-05-10 00:50:00 +01:00
Justin Clark-Casey (justincc) 80030d3f15 Perform SceneGraph.DuplicateObject() under existing m_updateLock already used for link and delinking, in order to avoid race conditions.
DuplicateObject() relies on source object having correct link numbers for the duration of the dupe.
Both link and delink can change link numbers such that they are not consistent for short periods of time.
2012-05-10 00:49:37 +01:00
Oren Hurvitz 4eba4a37ed Log the full exception when errors occur in BaseHttpServer 2012-05-10 00:49:29 +01:00
Justin Clark-Casey (justincc) dd0858e204 For osGetGridNick(), osGetGridName(), osGetGridLoginURI() and osGetGridCustom(), try to read from the [GridInfoService] section on standalone rather than [GridInfo]
[GridInfoService] is the section that's actually in bin/config-include/StandaloneCommon.ini.example
2012-05-10 00:49:15 +01:00
Justin Clark-Casey (justincc) 25fa6ee699 refactor: Instead of performing a ScenePresence lookup twice over LocateClientObject() and GetClientScene(), do the lookup just once in LocateClientObject() 2012-05-10 00:49:08 +01:00
Justin Clark-Casey (justincc) 84dfffe0aa Fix a bug in FriendsModule.StatusNotify() where all subsequent friends would not be notified once a non-local friend was found. 2012-05-10 00:48:57 +01:00
Justin Clark-Casey (justincc) aba803c447 Change LongCallTime on WebUtil to 3000, to match the time where request handling is considered "slow".
This may be the wrong thing to do but stops lots of log spam in HG setups now that the monitoring is extended to other outgoing calls.
LongCallTime may need to be made configurable.
2012-05-10 00:47:59 +01:00
Justin Clark-Casey (justincc) 79aae63aff minor: Tweak BaseHttpServer message to make it clear that this relates to slow handling of inbound requests. 2012-05-10 00:47:43 +01:00
Justin Clark-Casey (justincc) 59e93b8ee3 Extend 'slow' request logging to other server outbound requests (forms, rest, async rest) as well as the existing logging on outbound OSD requests.
Also prints out the first 100 chars of any slow request data since this can contain useful info (such as agent ID).
2012-05-10 00:47:26 +01:00
Justin Clark-Casey (justincc) e0e63f312f Reinsert a 2000ms delay before closing a no longer required agent on the source region after teleport to resolve Imprudence teleport problems.
Viewers 1 and 3 are fine with doing this immediately.  However, Imprudence has a small delay (<200ms, >500ms) after receiving the AgentCompleteMovement reply packet on the destination region before regarding that region as the currnet region.
If Imprudence receives a DisableSimulator in this period, it quits.
We are not restoring the full 5000ms delay since this brings back a bug where teleports permanently fail if an avatar tries to teleport back too quickly.
This commit also sends the AgentCompleteMovement packet to the client before telling the source region to release its old agent, in order to further cut down any possibility of the DisableSimulator being recieved before the AgentMovementComplete.
2012-05-10 00:39:57 +01:00
Snoopy Pfeffer d453372f4e Fixes Mantis #5999. llSetLinkPrimitiveParams with PRIM_BUMP_SHINY did cause a runtime error. 2012-05-10 00:39:50 +01:00
Justin Clark-Casey (justincc) 0f5a77c5bd Remove the somewhat misleading logging of the string length of some unknown requests, as this appeared to be some kind of numbered error code.
This brings these messages into line with similar messages that did not do this.
2012-05-10 00:39:43 +01:00
Justin Clark-Casey (justincc) 0c96d7ea5c minor: resolve some mono compiler warnings 2012-05-10 00:39:35 +01:00
Justin Clark-Casey (justincc) 4b947cd6d3 Implement optional name and description on http stream handlers so that we can relate a slow request to what the handler actually does and the agent it serves, if applicable.
This is most useful for capabilities where the url is not self-describing.
2012-05-10 00:38:26 +01:00
Justin Clark-Casey (justincc) ca586ca809 Comment out the five second sleep in etm.DoTeleport() if the old agent needs to be closed because it is no longer in the child's view distance.
This sleep appears unnecessary since a sleep has already occurred in WaitForCallback() whilst waiting for the destination region to notify of teleport success.
There are no async operations between this sleep and the WaitForCallback()
If this sleep is present, then teleporting back to the source region within 5 seconds results in a disconnection.
If this sleep is commented out then teleporting quickly back and forth between two simulators appears to work without issue.
Tested on standalone, local grid and distributed grid.
Please revert if there's something that I've missed.
2012-05-10 00:29:02 +01:00
Justin Clark-Casey (justincc) 880358f46b Remove some test code that accidentally crept in with 9d2e1c67 2012-05-10 00:28:53 +01:00
Justin Clark-Casey (justincc) 3393babb7d Add regression test for teleporting between neighbouring regions on the same simulator
This adds a non-advertised wait_for_callback option in [EntityTransfer].  Default is always true.
Teleport tests disable the wait for callback from the destination region in order to run within a single thread.
2012-05-10 00:28:47 +01:00
Justin Clark-Casey (justincc) c3ae90c067 Move max teleport distance check down into etm.DoTeleport() since this should apply to all teleport calls, not just those through Teleport() 2012-05-10 00:28:27 +01:00
Justin Clark-Casey (justincc) 25983f20a0 refactor: Split most of EntityTransferModule.Teleport() into its same region and different region teleport components.
DoTeleport() now retrives IEventQueue itself rather than requiring it to be passed in.
2012-05-10 00:25:25 +01:00
Justin Clark-Casey (justincc) 1441758bc6 Create TestHelpers.EnableLogging() and DisableLogging() to turn logging on and off within tests.
This makes *.Tests.dll.config files no longer needed, hence deleted.
2012-05-10 00:25:14 +01:00
Justin Clark-Casey (justincc) c7bbeb4490 Add request verb and url to error messages in WebUtil that lack this.
Make exception printing consistent across windows and mono.

Conflicts:

	OpenSim/Framework/WebUtil.cs
2012-05-10 00:21:09 +01:00
Diva Canto 6145f90423 Slight rewording of output messages. 2012-05-10 00:17:36 +01:00
Diva Canto 2e397d1514 HG: Moved User-level code down to the HGEntityTransferModule where it belongs. 2012-05-10 00:16:51 +01:00
Diva Canto a5d0a29dd9 Moved the inventory manipulation from HGEntityTransferModule to HGInventoryAccessModule where it belongs. They need to exchange some events, so added those to EventManager. Those events (TeleportStart and TeleportFail) are nice to have anyway. 2012-05-10 00:10:18 +01:00
Melanie de843fd0a8 Implement bulk inventory update over CAPS (not recursive by design,
do NOT CHANGE THIS, needed for HG 2.0)
2012-05-10 00:05:47 +01:00
Melanie ced4eeddcf Typo fix 2012-05-10 00:05:41 +01:00
Melanie 093910e90e Fix typos 2012-05-10 00:05:32 +01:00
Melanie 37685ec1b4 Start on Bulk inventory update via CAPS. Not functional yet. HG v2 2012-05-10 00:05:26 +01:00
Melanie ccd7d35b3f Add a corresponding method for items. HG v2 2012-05-10 00:05:19 +01:00
Melanie de7e0d7e52 Add SendRemoveInventoryFolders which allows to remove one or more
folders from the viewer's inventory view. For HG v2.0. More to come
2012-05-10 00:05:13 +01:00
Diva Canto 89ee03a24d HG: beginning of a more restrictive inventory access procedure (optional). Experimental: we'll try switching the root folder from under the viewer. 2012-05-10 00:02:14 +01:00
Melanie 79d1d3ca55 Commit the avination Teleport() methods (adaptedto justincc's changes) 2012-05-09 23:58:42 +01:00
Justin Clark-Casey (justincc) 675c208c7e zero out SP velocity before calling SP.Teleport(), as the client expects (though this is also effectively done by physics at the moment) 2012-05-09 23:58:35 +01:00
Justin Clark-Casey (justincc) b3307850ab refactor: Combine ScenePresence.Teleport() and TeleportWithMomentum()
These are identical apart from setting Velocity = zero, which has no practical effect anyway since this is zeroed when the avatar is added back to the physics scene.
2012-05-09 23:58:27 +01:00
Oren Hurvitz eaa840dbd9 OSSL: fixed the threat level check for osParseJSONNew 2012-05-09 23:57:49 +01:00
Justin Clark-Casey (justincc) f64089fa6c Restore _parent_scene.actor_name_map[prim_geom] = this; accidentally removed from ODEPrim.SetGeom.
This occurred in 7a574be3fd from Sat 21 Apr 2012.
This should fix collision detection.
Mnay thanks to tglion for the spot and the fix in http://opensimulator.org/mantis/view.php?id=5988
2012-05-09 23:57:27 +01:00
Justin Clark-Casey (justincc) 5157d2023d refactor: simply some properties code in BasicPhysicsPlugin 2012-05-09 23:52:41 +01:00
Justin Clark-Casey (justincc) 2cd927bb14 Fix bug where setting phantom on a prim would result in a server log message rather than setting phantom.
This was an oversight when removing some race conditions from PhysicsActor setting recently.
Regression tests extended to probe this code path.
Extending regression tests required implementation of a BasicPhysicsPrim (there was none before).  However, BasicPhysics plugin is still of no current practical use other than to fill in as a component for other parts of regression testing.
2012-05-09 23:52:04 +01:00
Justin Clark-Casey (justincc) 2889961622 Comment out spurious Body != IntPtr.Zero code after disableBody(), since disableBody() sets Body == IntPtr.Zero on all code paths. 2012-05-09 23:51:56 +01:00
Justin Clark-Casey (justincc) 232f59749e refactor: Simplify ODEPrim.AddChildPrim() by returning early where appropriate. 2012-05-09 23:51:48 +01:00
Justin Clark-Casey (justincc) d368a10cc7 Add test for setting physics in a linkset 2012-05-09 23:51:41 +01:00
Justin Clark-Casey (justincc) 139b848774 Add regression test for prim status when root prim in a new linkset is non-physical 2012-05-09 23:51:34 +01:00
Justin Clark-Casey (justincc) 74a5226af5 Fix a bug where linking a non-physical prim with a physical prim as root would make the non-physical prim phantom rather than part of the physics object.
On region restart, the whole object would become physical as expected.
Observed behaviour from elsewhere is that all prims in a new linkset should take on the status of the root prim.
Add regression test for this behaviour.
2012-05-09 23:51:25 +01:00
Justin Clark-Casey (justincc) c7ddc7a633 Remove redundant prim_geom != IntPtr.Zero checks in ODEPrim.
prim_geom == IntPtr.Zero only before a new add prim taint is processed (which is the first taint) or in operations such as scale change which are done in taint or under lock.
Therefore, we can remove these checks which were not consistently applied anyway.
If there is a genuine problem, better to see it quickly in a NullReferenceException than hide the bug.
2012-05-09 23:39:47 +01:00
Justin Clark-Casey (justincc) 265707d21c If a physical prim is manually moved (e.g. by a user) then set the geometry position as well as the body position
This is necessary to stop the moved prim snapping back to the original position on deselection if moved only once
This resolves http://opensimulator.org/mantis/view.php?id=5966
2012-05-09 23:39:37 +01:00
Justin Clark-Casey (justincc) eb39d1c4d4 Comment out debug [ASYNC DELETER] messages for now. 2012-04-30 19:29:17 +01:00
Justin Clark-Casey (justincc) 1197d48fc7 Remove mono compiler warning. Adjust message log to error from info 2012-04-30 19:29:08 +01:00
Justin Clark-Casey (justincc) 23e1a55ed5 Add text about using double quotes to surround console command arguments containing spaces to "help" text.
e.g. show object name "My long object name"
2012-04-30 19:29:01 +01:00
Justin Clark-Casey (justincc) ba2a539603 Put scene object related console commands into new "Objects" help category rather than "Regions" 2012-04-30 19:28:54 +01:00
Justin Clark-Casey (justincc) 8a8093d8dd Add flags information (phantom, physics, etc.) to "show object" and "show part" console commands 2012-04-30 19:28:41 +01:00
Justin Clark-Casey (justincc) 3fb0103452 Add regression test for teleporting an agent between separated regions on the same simulator.
This involves a large amount of change in test scene setup code to allow test scenes to share shared modules
SetupScene is now an instance method that requires an instantiation of SceneHelpers, though other SceneHelpers methods are still static
May split these out into separate classes in the future.
2012-04-30 19:27:21 +01:00
Justin Clark-Casey (justincc) aeefdaedc7 minor: make NPC tests run in a given order, comment out log lines in mock region data plugins, null out scene in script and npc torture tests, add other doc comments to torture tests 2012-04-30 19:18:54 +01:00
Justin Clark-Casey (justincc) 756d1f917f Stop individually deleting objects at the end of each ObjectTortureTest.
We can now do this since the entire scene and all objects within it are now successfully gc'd at the end of these tests.
This greatly improves the time taken to run each test (by reducing teardown time, not the time to actually do the test work that we're interested in).
Slightly simplifies config read in Scene constructor to help facilitate this.
2012-04-30 19:18:47 +01:00
Justin Clark-Casey (justincc) 6fa3dffad2 Use a fully stubbed out MockConsole for unit tests rather than inheriting from CommandConsole.
This is so that the static MainConsole.Instance doesn't retain references to methods registered by scene and other modules to service commands.
This prevents the scene from being garbage collected at the end of a test.
This is not the final thing preventing GC - next up is the timer started by SimStatsReporter that holds a reference to Scene that prevents end of test gc.
2012-04-30 19:17:06 +01:00
Justin Clark-Casey (justincc) 123e781cb3 Make TestSetPhysicsSinglePrim() actually add the object to the scene in order to test more code paths. 2012-04-30 19:15:07 +01:00
Justin Clark-Casey (justincc) ed9bf5b0c6 Add regression test for prim status when root prim in a new linkset is non-physical 2012-04-30 19:14:35 +01:00
Justin Clark-Casey (justincc) dd4e39ca1d refactor: extract common setup code in SceneObjectStatusTests 2012-04-30 19:13:33 +01:00
Justin Clark-Casey (justincc) 5a551b074b Add TestSetPhysics() to SOP status tests 2012-04-30 19:13:24 +01:00
Justin Clark-Casey (justincc) c1a9355865 Tweak log messages on local region to region teleport path to help with problem resolution. 2012-04-30 19:05:27 +01:00
Diva Canto 3ea6c25fb6 Teleports: bounce off repeated requests of teleporting the same agent. Some scripts do that, and that fails the whole thing. 2012-04-30 19:05:24 +01:00
Justin Clark-Casey (justincc) 2d3135448c Comment out old Scene.HandleLogOffUserFromGrid() to reduce client closing analysis complexity 2012-04-30 19:01:30 +01:00
Justin Clark-Casey (justincc) 36a99af37c minor: Add more detail to unauthorized caps client message 2012-04-30 19:01:23 +01:00
Justin Clark-Casey (justincc) 2aefd15913 minor: Add region name to dropped inbound packet message 2012-04-30 19:01:13 +01:00
Justin Clark-Casey (justincc) 6bc55b1086 minor: Add avatar name to removing agent log message 2012-04-30 19:00:47 +01:00
Justin Clark-Casey (justincc) 7058ce2c70 Comment out avatar move to target message for now. 2012-04-30 19:00:39 +01:00
Justin Clark-Casey (justincc) 8e111e9018 Add regression test TestSameRegionTeleport() 2012-04-30 18:59:50 +01:00
Justin Clark-Casey (justincc) d8bd7ca436 Comment out AvatarService.SetAvatar debug log line for now 2012-04-30 18:59:43 +01:00
Justin Clark-Casey (justincc) 392f73a000 Comment out some debug ATTACHMENTS log messages for now. 2012-04-30 18:59:35 +01:00
Justin Clark-Casey (justincc) 67efbaf33b Comment out the noisier AVFACTORY log messages for now.
Permanently comment out warnings about ScenePresence not being found - this is entirely expected if the avatar has alraedy logged out or left the scene.
2012-04-30 18:59:27 +01:00
Justin Clark-Casey (justincc) 0d06740148 Improve teleport log debug and error messages to tell us who is teleporting. 2012-04-30 18:58:37 +01:00
Diva Canto eda6947a22 Changed the Map-related messages from Info to Debug. They're debug messages. 2012-04-30 18:49:07 +01:00
Justin Clark-Casey (justincc) f331173145 Add online/offline indicator to "friends show" region console command.
Improve output table formatting.
2012-04-30 18:48:57 +01:00
Justin Clark-Casey (justincc) a666cd9e1f Add osForceAttachToAvatar() and osForceDetachFromAvatar()
These behave identically to llAttachToAvatar() and llDetachFromAvatar() except that they do not enforce the PERMISSION_ATTACH check
Intended for use in completely controlled dedicated environments where these checks are more a UI hinderance than a help.
Threat level high.
2012-04-24 00:50:32 +01:00
Justin Clark-Casey (justincc) 2657aa6987 Replace common code to fetch self inventory item (as opposed to uuid) with GetSelfInventoryItem()
However, at some point it would be far more convenient to receive the TaskInventoryItem in the constructor rather than just the item UUID, so we don't have to constantly refetch our self item.
2012-04-24 00:45:09 +01:00
Justin Clark-Casey (justincc) 6610cd2332 refactor: Replace calls to InventorySelf() with existing m_itemID in LSL_Api
There's no point look up an item ID that we already have.
2012-04-24 00:44:57 +01:00
Justin Clark-Casey (justincc) 0c8b44d514 Add more exception detail to Exception and IOException throws in BaseHttpServer.HandleRequest() 2012-04-24 00:40:19 +01:00
Justin Clark-Casey (justincc) ec46ff4445 Stop teleports from dropping tall avatars through or embedding them in the floor when lured by short avatars.
This involves giving the ceiling of the Z-component in a lure rather than the floor.
Ideally we would give the exact float compensating for relative avatar height but it looks like that isn't possible with the parcel id format used in lures
2012-04-24 00:37:37 +01:00
Melanie db891880e6 Fix a logic error in app domain creation 2012-04-24 00:36:54 +01:00
Melanie 9c433e8c50 Don't re-add the assembly resolver for each script if not creating the appdomain 2012-04-24 00:36:46 +01:00
Justin Clark-Casey (justincc) 5141863ae3 On "show part" command, show link number.
This replaces the Parts count which was rather pointless for a prim (it was either 1 if a child or the number of parts if the root).
This information is still avaliable on the "show object" command.
2012-04-18 23:02:02 +01:00
Justin Clark-Casey (justincc) d23550dea5 minor: Add some method doc. Add warnings since calling SOG link/delink methods directly rather than through Scene may allow race conditions. 2012-04-18 23:01:56 +01:00
Justin Clark-Casey (justincc) c3b12510ae Add TestGetChildPartPositionAfterObjectRotation() 2012-04-18 23:01:42 +01:00
Justin Clark-Casey (justincc) b2685e3671 Add test TestGetChildPartPosition() 2012-04-18 23:01:33 +01:00
Justin Clark-Casey (justincc) 601d2ddbf3 Move some public methods on WebStatsModule to private to reduce some static analysis complexity.
There's no obvious reason for these methods to be public.
2012-04-18 23:01:27 +01:00
Justin Clark-Casey (justincc) a5e8fe70af Use INSERT OR REPLACE INTO sql in WebStatsModule for session update rather than separate insert and update statements 2012-04-18 23:01:12 +01:00
Justin Clark-Casey (justincc) 9b3a96aa81 correct bug where f_invalid was being inserted on a webstats update for an existing session rather than d_world_kb 2012-04-18 23:01:06 +01:00
Justin Clark-Casey (justincc) d674e815bd Simplify WebStatsModule by removing the uncompleted migrations section.
Use "create table if not exists" instead.
Client stats data is transitory data that it is not worth migrating.
2012-04-18 23:01:00 +01:00
Justin Clark-Casey (justincc) c2e696d686 Fix bug in WebStatsModule where an exception would always be output on update if the user teleported to another region on that simulator.
This was because update was looking for an existing stats record unique in session id, agent id and region id.
But if the user teleports to another region then region id changes.
WebStatsModule promptly doesn't find the existing record and tries to insert a new one, but only session id is the primary key and that's still the same, which makes things go bang.
This makes the update search only on the unique session id.
This is only an issue with simulators that have multiple regions where the webstats module is enabled.
2012-04-18 23:00:51 +01:00
Justin Clark-Casey (justincc) 411dbb8df4 Add GroupPosition and GetWorldPosition() checks to TestGetRootPartPosition() 2012-04-18 23:00:43 +01:00
Justin Clark-Casey (justincc) b22dfbbf15 minor: make test names consistent 2012-04-18 23:00:36 +01:00
Justin Clark-Casey (justincc) 4c39a3fdbf refactor: move common init code into SetUp() in SceneObjectSpatialTests 2012-04-18 23:00:30 +01:00
Justin Clark-Casey (justincc) f3eb366f24 refactor: put SOG position test in a separate TestSceneObjectGroupPosition() 2012-04-18 23:00:22 +01:00
Justin Clark-Casey (justincc) a20d1b8f6b Add simple RelativePosition and OffsetPosition checks to TestGetRootPartPosition 2012-04-18 23:00:14 +01:00
Justin Clark-Casey (justincc) 0a51289332 Add very basic TestGetRootPartPosition() test 2012-04-18 23:00:02 +01:00
Justin Clark-Casey (justincc) 97ebfb00b4 Rather than having a FromFolderID property on every single prim and only ever using the root prim one, store on SOG instead.
This reduces pointless memory usage.
2012-04-18 22:59:24 +01:00
Justin Clark-Casey (justincc) c7d664f9d0 Store FromItemID for attachments once on SOG instead of on every SOP and only ever using the root part entry.
This eliminates some pointless memory use.
2012-04-18 22:59:18 +01:00
Justin Clark-Casey (justincc) c2fbaaa95d refactor: Eliminate unnecessary SOP.m_physActor 2012-04-18 22:59:08 +01:00
Justin Clark-Casey (justincc) 84d4b390f1 remove possible PhysActor unexpectedly null race conditions when changing prim collision status
factor out common SOP physics scene adding code into a common SOP.AddToPhysics() that is the counterpart to the existing RemoveFromPhysics()
2012-04-18 22:58:17 +01:00
Justin Clark-Casey (justincc) 54e59099b7 Fix more SOP.PhysActor race conditions in LSL_Api 2012-04-18 22:58:10 +01:00
Justin Clark-Casey (justincc) d9585ba37e Eliminate race condition where many callers would check SOP.PhysicsActor != null then assume it was still not null in later code.
Another thread could come and turn off physics for a part (null PhysicsActor) at any point.
Had to turn off localCopy on warp3D CoreModules section in prebuild.xml since on current nant this copies all DLLs in bin/ which can be a very large number with compiled DLLs
No obvious reason for doing that copy - nothing else does it.
2012-04-18 22:58:03 +01:00
Justin Clark-Casey (justincc) 45c617b5c3 Allow llRegionSayTo() to work on the PUBLIC_CHANNEL, as per http://wiki.secondlife.com/wiki/LlRegionSayTo
Addresses http://opensimulator.org/mantis/view.php?id=5950
2012-04-18 22:55:30 +01:00
Justin Clark-Casey (justincc) 4b0c78c64f minor: remove some now unneeded code from FriendsCommandsModule 2012-04-18 22:55:12 +01:00
Justin Clark-Casey (justincc) dd36e23a62 Make default "show friends" console command show friends fetched from the friends service.
There is no a --cache option which will show friends from the local cache if available.
2012-04-18 22:55:05 +01:00
Justin Clark-Casey (justincc) e2dade05d9 Lock NullFriendsData.m_Data for consistency and against concurrent read/write 2012-04-18 22:54:57 +01:00
Justin Clark-Casey (justincc) fbd61106cb refactor: Move "friends show cache" console command out into separate FriendsCommandsModule.
Expose required methods on IFriendsModule.  Rename GetFriends() -> GetFriendsFromCache() for self-documentation
2012-04-18 22:54:45 +01:00
Justin Clark-Casey (justincc) 67e66a2d34 Add simple login test with online friends. Add IFriendsModule.GrantRights() for granting rights via a module call.
Rename IFriendsModule.GetFriendPerms() -> GetRightsGrantedByFriend() to be more self-documenting and consistent with friends module terminology.
Add some method doc.
2012-04-18 22:46:10 +01:00
Justin Clark-Casey (justincc) 59911963ca refactor: Stop passing both IClientAPI and agentID to friend event listeners, these are redundant. Replace a few magic numbers with FriendRights enum already used elsewhere. 2012-04-18 22:45:31 +01:00
Justin Clark-Casey (justincc) dc2a4a6ccd Add simple regression test for logging in with offline friends. Don't expect to receive any in this instance. 2012-04-18 22:41:19 +01:00
Justin Clark-Casey (justincc) 81fb0b4f07 Add back parts of reverted changes that were not concerned with child agent caching.
This adds ScenePresence to IClientAPI.SceneAgent earlier on in the add client process so that its information is available to EventManager.OnNewClient() and OnClientLogin()
Also add a code comment as to why we're caching friend information for child agents.
2012-04-18 22:41:12 +01:00
Melanie a06c8fb7b2 Also add OSS header to interface 2012-04-18 22:41:05 +01:00
Melanie 05e70f76a9 Change namespace on CallingCardModule and correct interface file placemant. Also ass OpenSource header 2012-04-18 22:36:24 +01:00
Melanie b9f4836d3e Committing the Avination calling card module 2012-04-18 22:36:03 +01:00
Melanie ef77dc932b Adding the Avination calling card interface 2012-04-18 22:35:57 +01:00
Justin Clark-Casey (justincc) bd5b1d4d48 Earlier fix to remove localCopy on prebuild 2012-04-18 22:35:27 +01:00
Melanie 5c2ffa260c Pushing the Avination Calling card hooks. Module to follow. 2012-04-18 22:35:11 +01:00
Justin Clark-Casey (justincc) 23d04fa25c Add "friends show cache <first-name> <last-name>" command for debugging purposes.
This adds a reverse lookup (name -> ID) to IUserManagement instead of hitting the UserAccountService directly.
2012-04-18 22:11:42 +01:00
Justin Clark-Casey (justincc) 67dbce4512 minor: Add some documentation to OnNewClient and OnClientClosed events 2012-04-18 22:11:31 +01:00
Justin Clark-Casey (justincc) 46170fd0d8 minor: clean up some code formatting in VivoxVoiceModule.cs 2012-04-18 22:11:18 +01:00
Justin Clark-Casey (justincc) f85a453dc8 Allow the user to enter help topics in upper or lowercase.
Forcing uppercase (e.g. help Assets) is too annoying.
Thanks to WhiteStar for pointing this out.
2012-04-18 22:10:27 +01:00
nebadon bcfe48e05b fix yield prolog so it compiles with mono 2.11 there has been a bugzilla
report files with mono project in regards to this change, this simply
lets us move forward with using mono 2.11 for now :
https://bugzilla.xamarin.com/show_bug.cgi?id=4052
2012-04-18 22:10:05 +01:00
Justin Clark-Casey (justincc) 722ca250ea Move "change region" command into general category 2012-04-18 22:05:45 +01:00
Justin Clark-Casey (justincc) f4df128e52 Uses shorter AddCommand form for "show estates" 2012-04-18 22:05:38 +01:00
Justin Clark-Casey (justincc) 8cc5322b39 Display help commander topics in capitalized form - the commands themselves are still lowercase.
Also convert the estate commands to simply AddCommand() calls so that commands from two different modules can be placed in the same category
2012-04-18 22:05:24 +01:00
Justin Clark-Casey (justincc) 1480845597 Change "help" to display categories/module list then "help <category/module>" to display commands in a category.
This is to deal with the hundred lines of command splurge when one previously typed "help"
Modelled somewhat on the mysql console
One can still type help <command> to get per command help at any point.
Categories capitalized to avoid conflict with the all-lowercase commands (except for commander system, as of yet).
Does not affect command parsing or any other aspects of the console apart from the help system.
Backwards compatible with existing modules.
2012-04-18 22:05:03 +01:00
Justin Clark-Casey (justincc) c877e73463 Comment out log message about sending periodic appearance updates. 2012-03-30 02:33:26 +01:00
Justin Clark-Casey (justincc) 3ce5e8eb6c Add information about SendPeriodicAppearanceUpdates to OpenSimDefaults.ini for now.
Default remains false.
2012-03-30 02:33:18 +01:00
Justin Clark-Casey (justincc) e6b12e1f9d Add experimental SendPeriodicAppearanceUpdates = true/false setting to [Startup] in OpenSim.ini
On osgrid and other places, I have observed that manually sending appearance updates from the console often relieves grey avatar syndrome.
Despite hunting high and low, I haven't been able to find where this packet is sometimes being lost - it might be a persistent viewer bug for all I know.
Therefore, this experimental setting resends appearance data for everybody in the scene every 60 seconds.  These packets are small and the viewer only fetches texture
data if it doesn't already have it.
Default is false.
2012-03-30 02:33:10 +01:00
Justin Clark-Casey (justincc) bfbbd4ccba Add a scene maintenance thread in parallel to the heartbeat thread. The maintenance thread will end up running regular jobs that don't need to be in the main scene loop.
The idea is to make the critical main scene loop as skinny as possible - it doesn't need to run things that aren't time critical and don't depend on update ordering.
This will be done gradually over time to try and uncover any issues.  Many non-criticial scene loop activities are being launched on separate threadpool threads anyway.
This may also allow modules to register their own maintenance jobs without having to maintain their own timers and threads.
Currently the maintenance loop runs once a second, as opposed to the 89ms scene loop.
2012-03-30 02:33:01 +01:00
Justin Clark-Casey (justincc) fec7016665 Remove unnecessary shutting down check in Scene.Heartbeat(). Add some method doc. Rename HeartbeatThread, shuttingdown to conform to code standards. 2012-03-30 02:32:53 +01:00
Justin Clark-Casey (justincc) 47fe6170b2 Rename Scene.StartTimer() to Start() - this method no longer uses a timer. Comment out more effectively unused old heartbeat code. 2012-03-30 02:32:34 +01:00
Justin Clark-Casey (justincc) 24b5fb8523 Add commented out section on collisions switch in Scene.SetSceneCoreDebug().
This was not implemented before the recent changes but should be at some point.
2012-03-30 02:24:03 +01:00
Justin Clark-Casey (justincc) e8cd9688ce If "debug scene updates true" then print out to log when a garbage collection occurs. 2012-03-30 02:23:27 +01:00
Justin Clark-Casey (justincc) fa952f6d35 Add Scene.DebugUpdates switch which, if turned on, will print out a warning when a frame updates takes longer than twice the desired time
This is controlled via "debug scene updates true|false" on the region console.
Also fix an oversight with "debug scene teleport true|false"
2012-03-30 02:23:20 +01:00
Justin Clark-Casey (justincc) df55fd69af Incorporate scene teleporting debugging into "debug scene teleport true|false" command 2012-03-30 02:23:13 +01:00
Justin Clark-Casey (justincc) 019fc4c1f2 Replace "scene debug true false true" console command with "scene debug scripting true" or other parameters as appropriate.
This is to allow individual switching of scene debug settings and to provide flexibiltiy for additional settings.
2012-03-30 02:22:59 +01:00
Justin Clark-Casey (justincc) 22ea441feb fix compile error from last commit 2012-03-30 02:22:57 +01:00
Justin Clark-Casey (justincc) 9f5b33e52e refactor: simplify EstateManagementModule.handleEstateDebugRegionRequest() 2012-03-30 02:21:42 +01:00
Justin Clark-Casey (justincc) 92837c4f89 Add ability to log warn if a frame takes longer than twice the expected time. Currently commented out. 2012-03-30 02:21:32 +01:00
Justin Clark-Casey (justincc) 68ce06f40f remove unnecessary tmpFrameMS, use maintc instead for frame time calculation 2012-03-30 02:21:04 +01:00
Justin Clark-Casey (justincc) 279b31c75b Move frame loop entirely within Scene.Update() for better future performance analysis and stat accuracy.
Update() now accepts a frames parameter which can control the number of frames updated.
-1 will update until shutdown.
The watchdog updating moves above the maintc recalculation for any required sleep since it should be accounted for within the frame.
2012-03-30 02:20:46 +01:00
Justin Clark-Casey (justincc) 3117b3cd88 refactor: precalculate the fixed movement factor for avatar tilting (sqrt(2)) rather than doing it multiple times on every move. 2012-03-30 02:20:35 +01:00
Justin Clark-Casey (justincc) 9b547f76e7 refactor: Eliminate unnecessary duplicate avCapsuleTilted 2012-03-30 02:20:29 +01:00
Justin Clark-Casey (justincc) 3d6675784a Remove pointless ThreadAbortException catching in a test that isn't run anyway. 2012-03-30 02:20:21 +01:00
Justin Clark-Casey (justincc) 26f50eadd1 Remove some pointless catching/throwing in the scene loop. 2012-03-30 02:20:14 +01:00
Justin Clark-Casey (justincc) 6e8496ffc5 Comment out unused scene loop restart code.
This has actually been unused since at least 0.7.2 due to earlier changes.
2012-03-30 02:18:13 +01:00
Justin Clark-Casey (justincc) 88d6c4ec0e Use m_lastFrameTick instead of m_lastUpdate in Scene.GetHealth(). m_lastUpdate is no longer properly updated and is redundant anyway. 2012-03-30 02:18:05 +01:00
Justin Clark-Casey (justincc) 135eeb45d6 Change flavour to extended 2012-03-30 02:16:11 +01:00
Justin Clark-Casey (justincc) 54ee59c0bb Add Extended flavour option to opensim version information.
This flavour is for changes in addition to the 0.7.3-post-fixes branch that are too large to be considered fixes but should be reasonably stable.
This flavour will almost certainly never see a formal release.
2012-03-30 02:13:37 +01:00
Justin Clark-Casey (justincc) 4a5c61a33d Enable voice by default on parcels to weaken effects of viewer 2/3 ParcelVoiceInfoRequest bug
Viewer 2/3 contains a bug where the viewer will constantly retry ParcelVoiceInfoRequest requests on voice-disabled parcels where voice is otherwise available.
Attempts to fix this server-side have not been successful - sending a non-OK http code (e.g. a 404) just makes the viewer request again immediately.
Dropping the request entirely is a bit better but the viewer still retries after a minute.
Estate settings already enabled voice by default so doing the same for parcels.  This only has an effect if you have any voice system active at all.
Ultimately, the re-request bug needs to be fixed viewer-side (LL suffers from the same issue!) but it might be worth implementing the drop request hack.
2012-03-30 02:03:52 +01:00
Diva Canto 179c0f5f56 Merge branch '0.7.3-post-fixes' of ssh://opensimulator.org/var/git/opensim into 0.7.3-post-fixes 2012-03-22 20:36:01 -07:00
Justin Clark-Casey (justincc) 4dbf937707 Comment out login parameters debug output accidentally included with c4b2d24 2012-03-22 23:33:08 +00:00
Justin Clark-Casey (justincc) 9edb57e5e9 Comment out a terrain save-tile debugging message that accidentally crept in with c4b2d24 2012-03-22 23:17:54 +00:00
Justin Clark-Casey (justincc) 4d15ad63bf refactor: simplify code for checks when part.OwnerID != destPart.OwnerID in MoveTaskInventoryItem() 2012-03-22 23:03:00 +00:00
Justin Clark-Casey (justincc) 4021709371 Fix llGiveInventory() so that it checks the destination part for AllowInventoryDrop, not the source.
This allows llAllowInventoryDrop() to work.
Regression test added for this case.
2012-03-22 23:02:49 +00:00
Justin Clark-Casey (justincc) 3c13f5c3aa Add llGiveInventory() test from object to object where both objects are owned by the same user. 2012-03-22 23:02:35 +00:00
Justin Clark-Casey (justincc) 381517b451 Add prim name to "[MESH]: No recognized physics mesh..." log message 2012-03-22 23:01:39 +00:00
Justin Clark-Casey (justincc) 6ecf36d49c Fix small typo 2012-03-22 22:47:03 +00:00
Justin Clark-Casey (justincc) 64eb4b8408 Fix crash where two scene loop threads could changes m_MeshToTriMeshMap at the same time.
Have to lock m_MeshToTriMeshMap as property is static and with more than one region two scene loops could try to manipulate at the same time.
2012-03-22 22:46:45 +00:00
Diva Canto 318da3fdcd Added new simple_build_permissions config to the .ini and .example files. 2012-03-22 14:34:46 -07:00
Melanie 50c99fcda6 Change a false false to be truly true - or is this statement false?
Fixes perms boo-boo
2012-03-22 14:34:33 -07:00
Melanie 321de1f263 Rework Diva's patch to simplify it 2012-03-22 14:34:19 -07:00
Diva Canto fa30ace67d Fixed borkness with map search introduce by my last changes to it. 2012-03-20 17:49:05 -07:00
Justin Clark-Casey (justincc) 92baa79253 Add some doc about the EventManager.OnLoginsEnabled event. 2012-03-19 22:49:34 +00:00
Justin Clark-Casey (justincc) e861b45313 Fix a bug where logins to standalones would fail if the RegionReady module was not active
Unfortunately, the OnLoginsEnabled event is currently only guaranteed to fire if the RegionReady module is active.
However, we can instantiate the AuthorizationService in the module RegionLoaded method since by this time all other modules will have been loaded
2012-03-19 22:49:14 +00:00
Justin Clark-Casey (justincc) cf91ac68b6 Stop console command "xengine status" throwing an exception if there are no scripts in a region.
Addresses http://opensimulator.org/mantis/view.php?id=5940
2012-03-19 21:45:18 +00:00
Justin Clark-Casey (justincc) d4aba13526 Clean up "save iar" help 2012-03-19 21:33:03 +00:00
Justin Clark-Casey (justincc) d36c7c3782 minor: reuse threadpool count we just fetched instead of fetching it again 2012-03-19 21:32:50 +00:00
Justin Clark-Casey (justincc) 4385fcdeae Add total scripts count to "show threads"
However, this returns 0 on Mono (at least on 2.6.7)!  So not showing if it is zero.
2012-03-19 21:32:42 +00:00
Justin Clark-Casey (justincc) 04eb170624 refactor: separate out console and status report generation parts of XEngine 2012-03-19 21:32:34 +00:00
Justin Clark-Casey (justincc) 4803686078 Improve threadpool reporting to "show threads" console command (also gets printed out periodically) 2012-03-19 21:32:25 +00:00
Justin Clark-Casey (justincc) 20b0fda3bb Add process working memory to "show stats" memory statistics.
This shows the actual amount of RAM being taken up by OpenSimulator (objects + vm overhead)
2012-03-19 21:32:16 +00:00
Justin Clark-Casey (justincc) 4e5f823595 In Top Scripts report, don't show scripts with no or less than 1 microsecond of execution time.
This is to make the report clearer and less confusing.
2012-03-19 21:32:02 +00:00
Justin Clark-Casey (justincc) a74408d1d2 Aggregate script execution times by linksets rather than individual prims.
This is for the top scripts report.
2012-03-19 21:31:53 +00:00
Justin Clark-Casey (justincc) 8206537efd Fix owner name display in "Top Colliders" and "Top Script" region reports. 2012-03-19 21:31:45 +00:00
Justin Clark-Casey (justincc) a9a77bb3ab Replace script-lines-per-second with the script execution time scaled by its measurement period and an idealised frame time.
The previous lines-per-second measurement used for top scripts report was inaccurate, since lines executed does not reflect time taken to execute.
Also, every fetch of the report would reset all the numbers limiting its usefulness and we weren't even guaranteed to see the top 100.
The actual measurement value should be script execution time per frame but XEngine does not work this way.
Therefore, we use actual script execution time scaled by the measurement period and an idealised frame time.
This is still not ideal but gives reasonable results and allows scripts to be compared.
This commit moves script execution time calculations from SceneGraph into IScriptModule implementations.
2012-03-19 21:31:38 +00:00
Justin Clark-Casey (justincc) 6390de689d Remove property/field duplication in ScriptInstance where it's unnecessary. 2012-03-19 21:31:17 +00:00
Justin Clark-Casey (justincc) 41ce19836b Simplify some logic in the ScriptInstance constructor - running is set to false in both if/else branches 2012-03-19 21:31:07 +00:00
Melanie 883a4f6fff FireAndForget scripted rez - port from Avination 2012-03-19 21:30:31 +00:00
Justin Clark-Casey (justincc) 5f1da80fc1 minor: correct indentation levels 2012-03-19 21:30:16 +00:00
Justin Clark-Casey (justincc) 64217d67f6 Remove duplication of m_RunEvents and Running 2012-03-19 21:29:45 +00:00
Justin Clark-Casey (justincc) b01c79354c Fix a problem where multiple near simultaneous calls to llDie() from multiple scripts in the same linkset can cause unnecessary thread aborts.
The first llDie() could lock Scene.m_deleting_scene_object.
The second llDie() would then wait at this lock.
The first llDie() would go on to remove the second script but always abort it since the second script's WorkItem would not go away.
Easiest solution here is to remove the m_deleting_scene_object since it's no longer justified - we no longer lock m_parts but take a copy instead.
This also requires an adjustment in XEngine.OnRemoveScript not to use instance.ObjectID instead when firing the OnObjectRemoved event.
2012-03-19 21:29:34 +00:00
Justin Clark-Casey (justincc) 9ecbcb787c Alleviate an issue where calling Thread.Abort() on script WorkItems can fail to release locks, resulting in a crippled simulator.
This seems to be a particular problem with ReaderWriterLockSlim, though other locks can be affected as well.
It has been seen to happen when llDie() is called in a linkset running more than one script.
Alleviation here means supplying a ScriptInstance.Stop() timeout of 1000ms rather than 0ms, to give events a chance to complete.
Also, we check the IsRunning status at the top of the ScriptInstance.EventProcessor() so that another event doesn't start in the mean time.
Ultimately, a better solution may have to be found since a long-running event would still exceed the timeout and be aborted.
2012-03-19 21:29:24 +00:00
Justin Clark-Casey (justincc) e17e376b04 refactor: rename ScriptInstance.m_CurrentResult to m_CurrentWorkItem to make it more understandable as to what it is and what it does (hold a thread pool work item for a waiting of in-progress event)
Also add other various illustrative comments
2012-03-19 21:29:09 +00:00
Justin Clark-Casey (justincc) 1b4ea4f178 Add max thread and min thread information to "xengine status" region console command 2012-03-19 21:28:54 +00:00
Melanie 1de29fb362 Change OpenSim.ini.example to reflect how to actually enable prim limits,
as opposed to how it was first designed.
2012-03-19 21:28:37 +00:00
Justin Clark-Casey (justincc) 7e4bd492fd Add documentation to make more explicit the difference between OnRezScript and OnNewScript in the event manager
OnNewScript fires when a script is added to a scene
OnRezScript fires when the script actually runs (i.e. after permission checks, state retrieval, etc.)
2012-03-19 21:26:32 +00:00
Justin Clark-Casey (justincc) 588d56503d Remove unnecessary explicit ElapsedEventHandler in SimReporter 2012-03-19 21:26:12 +00:00
Justin Clark-Casey (justincc) e9602656f8 Add sensor, dataserver requests, timer and listener counts to "xengine status" command.
This is for diagnostic purposes.
2012-03-19 21:26:04 +00:00
Justin Clark-Casey (justincc) 0116d418f0 Fix TestSyntaxError() and TestSyntaxErrorDeclaringVariableInForLoop()
They were all failing assertions but the exceptions these threw were caught as expected Exceptions.
I don't think we can easily distinguish these from the Exceptions that we're expecting.
So for now we'll do some messy manually checking with boolean setting instead.
This patch also corrects the assertions themselves.
2012-03-19 21:25:41 +00:00
Justin Clark-Casey (justincc) 9992974c66 Get all test methods in OpenSim.Region.ScriptEngine.Tests.dll to report that they're running 2012-03-19 21:25:30 +00:00
Justin Clark-Casey (justincc) ba27d8a389 Fix off by one error in script error reporting. 2012-03-19 21:25:20 +00:00
Justin Clark-Casey (justincc) f96e985763 Simplify NPCModuleTests code by putting the NPCModule in an instance variable rather than making each test fetch it seperately.
Also rename instance variables in the test to conform to naming standards and for understandability
2012-03-19 21:25:07 +00:00
Diva Canto 5b9eaae50d Region access control! Region operators can now specify things like DisallowForeigners (means what it says) and DisallowResidents (means that only admins and managers can get into the region). This puts the never-completed AuthorizationService to good use. Note that I didn't implement a grid-wide Authorization service; this service implementation is done entirely locally on the simulator. This can be changed as usual by pluging in a different AuthorizationServicesConnector. 2012-03-17 19:49:14 -07:00
Diva Canto 74a13f7e3b Fixes mantis #5923 2012-03-17 19:47:05 -07:00
Diva Canto 3e88fc8aad Datasnapshot: added "secret" to the registration/deregistration query so that data providers can verify authenticity if they want. 2012-03-16 17:27:45 -07:00
Diva Canto 881740d702 DataSnapshot: renamed gridserverURL to gatekeeperURL, and normalimzed the capitalization of 'name' to lower case, also in the same <grid> section. 2012-03-16 17:27:29 -07:00
Diva Canto 9a643a1bb9 Terrain: added [Terrain] section with an option to load an initial flat terrain. Default is still pinhead island. I much rather have a flat land in the beginning.
Conflicts:

	bin/OpenSim.ini.example
2012-03-16 13:14:26 -07:00
Diva Canto a5488650ff More on map search: send extra messages to the user regarding the region being found or not, because the UI is horribly confusing -- places profile is always "loading..." whether the region exists or not. 2012-03-15 20:24:26 -07:00
Diva Canto a275127a65 More on SLURLs and V3. This is hacky, but it works. Basically, we have to redefine the encoding of HG URLs because the viewer messes them up. Examples of what works and doesn't work:
- secondlife://ucigrid00.nacs.uci.edu|8002/128/128 <-- works throughout the viewer
- secondlife://http|!!ucigrid00.nacs.uci.edu|8002+Test+Zone+1/128/128 <-- works throughout the viewer
- secondlife://http|!!grid.sciencesim.com!grid!hypergrid.php+Yellowstone01+74/128/128 <-- works throughout
- secondlife://http%3A%2F%2Fucigrid00.nacs.uci.edu%3A8002%20UCI%20Central%201/128/128 <-- works in chat, but not as URLs in the webkit
2012-03-15 16:14:20 -07:00
Diva Canto 02db31db6a Revert "Revert "More hacking around viewer bug""
This reverts commit 0434758a0d.
2012-03-15 16:14:07 -07:00
Diva Canto 8bd813e6fc Revert "Revert "Hack around https://jira.secondlife.com/browse/VWR-28570""
This reverts commit 09ff121654.
2012-03-15 16:13:50 -07:00
Diva Canto 09ff121654 Revert "Hack around https://jira.secondlife.com/browse/VWR-28570"
This reverts commit d7651a389e.
2012-03-15 14:38:22 -07:00
Diva Canto 0434758a0d Revert "More hacking around viewer bug"
This reverts commit 8bb0a71083.
2012-03-15 14:38:03 -07:00
Diva Canto 8bb0a71083 More hacking around viewer bug 2012-03-15 11:04:56 -07:00
Diva Canto d7651a389e Hack around https://jira.secondlife.com/browse/VWR-28570 2012-03-15 10:18:55 -07:00
Justin Clark-Casey (justincc) 824318a0c1 Go back to setting appearance directly in NPCModule.SetAppearance() to fix mantis 5914
The part reverted is from commit 2ebb421.
Unfortunately, IAvatarFactoryModule.SetAppearance() does not transfer attachments.
I'm not sure how to do this separately, unfortunately I'll need to leave it to Dan :)
Regression test added for this case.
Mantis ref: http://opensimulator.org/mantis/view.php?id=5914
2012-03-06 01:32:44 +00:00
Justin Clark-Casey (justincc) 5e9ed22e84 Merge branch '0.7.3-post-fixes' of ssh://opensimulator.org/var/git/opensim into 0.7.3-post-fixes 2012-03-06 00:48:24 +00:00
Chris Hart a6c611e7c9 Updates to MSSQL store for 0.7.3 to include:
* Telehub support
* Bugfix to Friends lookups
* Updates to Creator fields to store up to 255 characters for HG item creator storage
2012-03-06 00:45:58 +00:00
Diva Canto 72b325f8b5 Send the right name and creation date on the BasicProfileModule. 2012-03-01 19:58:57 -08:00
Justin Clark-Casey (justincc) 54d0514b13 Move SenseRepeaters.Count check inside the SenseRepeatListLock.
No methods in the List class are thread safe in the MS specification/documentation
2012-03-02 00:37:48 +00:00
Justin Clark-Casey (justincc) 58b1c3cec0 lock SenseRepeatListLock when added a new sensor during script reconstitution.
This is already being done in the other place where a sensor is added.
Adding a sensor whilst another thread is iterating over the sensor list can cause a concurrency exception.
2012-03-02 00:37:42 +00:00
Justin Clark-Casey (justincc) 71641523a3 Flick 0.7.3-post-fixes to Flavour.Post_Fixes 2012-02-29 23:43:41 +00:00
Justin Clark-Casey (justincc) 94c5e25c3b Extend distsrc target to cleanup the files generated by running prebuild 2012-02-29 22:32:32 +00:00
Justin Clark-Casey (justincc) 20bad0aa6c Merge branch '0.7.3-post-fixes' of ssh://opensimulator.org/var/git/opensim into 0.7.3-post-fixes 2012-02-29 22:22:42 +00:00
Justin Clark-Casey (justincc) e7f23a6218 Switch flavour to release 2012-02-29 22:10:33 +00:00
Justin Clark-Casey (justincc) 25c29db8b6 Don't start pCampbot if the user doesn't supply bot firstname, lastname stub and password 2012-02-29 22:04:17 +00:00
Justin Clark-Casey (justincc) 1750fba9ce Call Dispose() via using() on SqliteCommands in WebStatsModule after use. 2012-02-29 22:04:04 +00:00
PixelTomsen b18e410586 PRIM_SCULPT_FLAG_INVERT, PRIM_SCULPT_FLAG_MIRROR implemented
http://opensimulator.org/mantis/view.php?id=5763
2012-02-29 22:03:28 +00:00
Justin Clark-Casey (justincc) 38d5e1fab3 Move libopenjpeg native libraries into lib32 and lib64 as appropriate. 2012-02-29 22:03:15 +00:00
Justin Clark-Casey (justincc) 4180c32eb1 Remove some more unused Bullet libraries. 2012-02-29 22:03:08 +00:00
Justin Clark-Casey (justincc) 5115229fdf Remove old libbulletnet native libraries. These are not used in the current generation bullet physics plugin. 2012-02-29 22:02:59 +00:00
Justin Clark-Casey (justincc) e8f2d814e7 Move other sqlite and ode 32-bit and 64-bit libraries into lib32 or lib64 as appropriate. 2012-02-29 22:02:50 +00:00
Diva Canto 1fda8c5a86 HG: Remove async in posting assets to foreign grid. Mono hates concurrency there. 2012-02-26 14:30:58 -08:00
Justin Clark-Casey (justincc) 6b77b55d40 Merge branch 'master' into 0.7.3-post-fixes 2012-02-25 00:49:16 +00:00
Justin Clark-Casey (justincc) 82cdb08c1f Merge branch 'master' into 0.7.3-post-fixes 2012-02-25 00:49:05 +00:00
Justin Clark-Casey (justincc) dafcb3bcd7 Merge branch 'master' into 0.7.3-post-fixes 2012-02-24 23:35:59 +00:00
Diva Canto 3259b1d1e0 Amend to last commit: synchronize access to queues. 2012-02-20 11:13:02 -08:00
Diva Canto 512910a51f More improvements on agent position updates: if the target sims fail, blacklist them for 2 min, so that we don't keep doing remote calls that fail. 2012-02-20 11:00:01 -08:00
Diva Canto fdda57cf10 Merge branch '0.7.3-post-fixes' of ssh://opensimulator.org/var/git/opensim into 0.7.3-post-fixes 2012-02-19 16:48:09 -08:00
Diva Canto ec8e34950d One more tweak related to the previous 2 commits. 2012-02-19 16:47:04 -08:00
Diva Canto 93964ef3a4 Amend to last commit. This should have been committed too. 2012-02-19 16:46:47 -08:00
Diva Canto 5c8af6a136 A few more tweaks on position updates and create child agents. Mono hates concurrent uses of the same TCP connection, and even of the connections to the same server. So let's stop doing it. This patch makes movement much smoother when there are lots of neighbours. 2012-02-19 16:46:32 -08:00
PixelTomsen 4d0c8aca05 Fix:OmegaX, OmegaY and OmegaZ not saved for child prims http://opensimulator.org/mantis/view.php?id=5893
Signed-off-by: nebadon <michael@osgrid.org>
2012-02-19 13:49:51 -05:00
PixelTomsen 8fc16ece96 Fix:Fly setting for Parcel dosen't work http://opensimulator.org/mantis/view.php?id=5887
Signed-off-by: nebadon <michael@osgrid.org>
2012-02-19 13:49:41 -05:00
BlueWall fcbb375e8f Use localy defined name, TPFlags, for Constants.TeleportFlags 2012-02-19 12:42:05 -05:00
BlueWall 49c65279fa Route logins according to Estate, Telehub and TeleportFlags 2012-02-19 12:41:44 -05:00
BlueWall 86e8a56fe1 Propagate our teleport flags on logins 2012-02-19 12:41:30 -05:00
BlueWall b199330682 Parcel sales support to SQLite 2012-02-19 12:41:11 -05:00
BlueWall 7a7ebaebd1 Fillin missing SQLite support for Telehubs 2012-02-19 12:40:46 -05:00
BlueWall 164ae0b24b Fix missing telehub handling on login 2012-02-19 12:40:26 -05:00
Diva Canto 7156545fca This should smooth movement in heteregeneous networks by a lot: cache the region by position instead of looking it up all the time -- this was being done during the main update loop! 2012-02-18 22:15:58 -08:00
Justin Clark-Casey (justincc) 73a5abf4d9 Merge branch 'master' into 0.7.3-post-fixes 2012-02-17 04:04:38 +00:00
Justin Clark-Casey (justincc) 630c8dc828 switch version flavour to rc2 2012-02-17 04:03:59 +00:00
Justin Clark-Casey (justincc) 6de89246c2 Merge branch 'master' into 0.7.3-post-fixes 2012-02-17 00:02:16 +00:00
Justin Clark-Casey (justincc) 96973a5778 Merge branch 'master' into 0.7.3-post-fixes 2012-02-16 03:39:25 +00:00
Justin Clark-Casey (justincc) 96843f2b17 Merge branch 'master' into 0.7.3-post-fixes 2012-02-15 02:41:50 +00:00
Justin Clark-Casey (justincc) 8a36f54cf4 Merge branch 'master' into 0.7.3-post-fixes 2012-02-06 20:54:21 +00:00
Justin Clark-Casey (justincc) 1a14e660d2 Merge branch 'master' into 0.7.3-post-fixes 2012-02-04 02:03:49 +00:00
Justin Clark-Casey (justincc) 2502aae5db Switch flavour to RC1. It will still be a while before RC1 is released. 2012-02-04 01:26:29 +00:00
396 changed files with 18279 additions and 9203 deletions

2
.gitignore vendored
View File

@ -41,6 +41,8 @@ bin/Physics*
bin/Terrain*
bin/Regions/*
bin/UserAssets
bin/assetcache
bin/maptiles
bin/estate_settings.xml
bin/config-include/CenomeCache.ini
bin/config-include/FlotsamCache.ini

View File

@ -8,6 +8,24 @@
<copy file="bin/OpenSim.ini.example" tofile="bin/OpenSim.ini"/>
<copy file="bin/config-include/StandaloneCommon.ini.example" tofile="bin/config-include/StandaloneCommon.ini"/>
<copy file="bin/config-include/FlotsamCache.ini.example" tofile="bin/config-include/FlotsamCache.ini"/>
<!-- delete files generated by runprebuild.sh which had to be run in order to generate the build file for this target-->
<delete>
<fileset basedir="OpenSim">
<include name="**/*.build"/>
<include name="**/*.csproj*"/>
<include name="**/*.dll.build"/>
<include name="**/*.pidb"/>
<exclude name="Tools/OpenSim.32BitLaunch/**"/>
<exclude name="Tools/Robust.32BitLaunch/**"/>
<exclude name="Tools/LaunchSLClient/**"/>
</fileset>
</delete>
<delete>
<fileset>
<include name="OpenSim.build"/>
<include name="OpenSim.sln"/>
</fileset>
</delete>
</target>
<property name="distbindir" value="distbin" />
@ -117,14 +135,25 @@
<delete dir="%temp%"/>
</target>
<target name="torture" depends="build, find-nunit">
<target name="test-stress" depends="build, find-nunit">
<setenv name="MONO_THREADS_PER_CPU" value="100" />
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.torture">
<arg value="./bin/OpenSim.Tests.Torture.dll" />
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.stress">
<arg value="./bin/OpenSim.Tests.Stress.dll" />
</exec>
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests.torture)==0}" />
<fail message="Failures reported in stress tests." unless="${int::parse(testresult.opensim.tests.stress)==0}" />
<delete dir="%temp%"/>
</target>
<target name="test-perf" depends="build, find-nunit">
<setenv name="MONO_THREADS_PER_CPU" value="100" />
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.performance">
<arg value="./bin/OpenSim.Tests.Performance.dll" />
</exec>
<fail message="Failures reported in performance tests." unless="${int::parse(testresult.opensim.tests.performance)==0}" />
<delete dir="%temp%"/>
</target>

View File

@ -1,4 +1,4 @@
The following people have contributed to OpenSim (Thank you
<<<>>>>The following people have contributed to OpenSim (Thank you
for your effort!)
= Current OpenSim Developers (in very rough order of appearance) =
@ -139,6 +139,9 @@ what it is today.
* SignpostMarv
* SpotOn3D
* Strawberry Fride
* Talun
* TechplexEngineer (Blake Bourque)
* TBG Renfold
* tglion
* tlaukkan/Tommil (Tommi S. E. Laukkanen, Bubble Cloud)
* tyre

View File

@ -539,7 +539,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
/// path has not already been registered, the method is added to the active
/// handler table.
/// </summary>
public void AddStreamHandler(string httpMethod, string path, RestMethod method)
{
if (!IsEnabled)

View File

@ -101,18 +101,8 @@ namespace OpenSim.Capabilities.Handlers
llsdItem.item_id = invItem.ID;
llsdItem.name = invItem.Name;
llsdItem.parent_id = invItem.Folder;
try
{
llsdItem.type = Utils.AssetTypeToString((AssetType)invItem.AssetType);
llsdItem.inv_type = Utils.InventoryTypeToString((InventoryType)invItem.InvType);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[WEB FETCH INV DESC HANDLER]: Problem setting asset {0} inventory {1} types while converting inventory item {2}: {3}",
invItem.AssetType, invItem.InvType, invItem.Name, e.Message);
}
llsdItem.type = invItem.AssetType;
llsdItem.inv_type = invItem.InvType;
llsdItem.permissions = new LLSDPermissions();
llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
@ -126,21 +116,7 @@ namespace OpenSim.Capabilities.Handlers
llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
llsdItem.sale_info = new LLSDSaleInfo();
llsdItem.sale_info.sale_price = invItem.SalePrice;
switch (invItem.SaleType)
{
default:
llsdItem.sale_info.sale_type = "not";
break;
case 1:
llsdItem.sale_info.sale_type = "original";
break;
case 2:
llsdItem.sale_info.sale_type = "copy";
break;
case 3:
llsdItem.sale_info.sale_type = "contents";
break;
}
llsdItem.sale_info.sale_type = invItem.SaleType;
return llsdItem;
}

View File

@ -63,7 +63,8 @@ namespace OpenSim.Capabilities.Handlers
FetchInventory2Handler fiHandler = new FetchInventory2Handler(m_InventoryService);
IRequestHandler reqHandler
= new RestStreamHandler("POST", "/CAPS/FetchInventory/", fiHandler.FetchInventoryRequest);
= new RestStreamHandler(
"POST", "/CAPS/FetchInventory/", fiHandler.FetchInventoryRequest, "FetchInventory", null);
server.AddStreamHandler(reqHandler);
}
}

View File

@ -66,13 +66,14 @@ namespace OpenSim.Capabilities.Handlers
throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
GetMeshHandler gmeshHandler = new GetMeshHandler(m_AssetService);
IRequestHandler reqHandler = new RestHTTPHandler("GET", "/CAPS/" + UUID.Random(),
delegate(Hashtable m_dhttpMethod)
{
return gmeshHandler.ProcessGetMesh(m_dhttpMethod, UUID.Zero, null);
});
IRequestHandler reqHandler
= new RestHTTPHandler(
"GET",
"/CAPS/" + UUID.Random(),
httpMethod => gmeshHandler.ProcessGetMesh(httpMethod, UUID.Zero, null),
"GetMesh",
null);
server.AddStreamHandler(reqHandler);
}
}
}

View File

@ -58,8 +58,8 @@ namespace OpenSim.Capabilities.Handlers
// TODO: Change this to a config option
const string REDIRECT_URL = null;
public GetTextureHandler(string path, IAssetService assService) :
base("GET", path)
public GetTextureHandler(string path, IAssetService assService, string name, string description)
: base("GET", path, name, description)
{
m_assetService = assService;
}
@ -77,7 +77,6 @@ namespace OpenSim.Capabilities.Handlers
{
m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service");
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
return null;
}
UUID textureID;
@ -115,7 +114,6 @@ namespace OpenSim.Capabilities.Handlers
// "[GETTEXTURE]: For texture {0} sending back response {1}, data length {2}",
// textureID, httpResponse.StatusCode, httpResponse.ContentLength);
httpResponse.Send();
return null;
}
@ -165,7 +163,7 @@ namespace OpenSim.Capabilities.Handlers
if (texture == null)
{
//m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
// m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
// Fetch locally or remotely. Misses return a 404
texture = m_assetService.Get(textureID.ToString());
@ -199,7 +197,7 @@ namespace OpenSim.Capabilities.Handlers
}
else // it was on the cache
{
//m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
// m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
WriteTextureData(httpRequest, httpResponse, texture, format);
return true;
}
@ -221,12 +219,30 @@ namespace OpenSim.Capabilities.Handlers
int start, end;
if (TryParseRange(range, out start, out end))
{
// Before clamping start make sure we can satisfy it in order to avoid
// sending back the last byte instead of an error status
if (start >= texture.Data.Length)
{
response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
m_log.DebugFormat(
"[GETTEXTURE]: Client requested range for texture {0} starting at {1} but texture has end of {2}",
texture.ID, start, texture.Data.Length);
// Stricly speaking, as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, we should be sending back
// Requested Range Not Satisfiable (416) here. However, it appears that at least recent implementations
// of the Linden Lab viewer (3.2.1 and 3.3.4 and probably earlier), a viewer that has previously
// received a very small texture may attempt to fetch bytes from the server past the
// range of data that it received originally. Whether this happens appears to depend on whether
// the viewer's estimation of how large a request it needs to make for certain discard levels
// (http://wiki.secondlife.com/wiki/Image_System#Discard_Level_and_Mip_Mapping), chiefly discard
// level 2. If this estimate is greater than the total texture size, returning a RequestedRangeNotSatisfiable
// here will cause the viewer to treat the texture as bad and never display the full resolution
// However, if we return PartialContent (or OK) instead, the viewer will display that resolution.
// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
// response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length));
// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
response.ContentType = texture.Metadata.ContentType;
}
else
{
@ -234,12 +250,18 @@ namespace OpenSim.Capabilities.Handlers
start = Utils.Clamp(start, 0, end);
int len = end - start + 1;
//m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
// Always return PartialContent, even if the range covered the entire data length
// We were accidentally sending back 404 before in this situation
// https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
// entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
//
// We also do not want to send back OK even if the whole range was satisfiable since this causes
// HTTP textures on at least Imprudence 1.4.0-beta2 to never display the final texture quality.
// if (end > maxEnd)
// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
// else
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
response.ContentLength = len;

View File

@ -62,8 +62,8 @@ 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));
server.AddStreamHandler(new GetTextureHandler("/CAPS/GetTexture/" /*+ UUID.Random() */, m_AssetService));
server.AddStreamHandler(
new GetTextureHandler("/CAPS/GetTexture/" /*+ UUID.Random() */, m_AssetService, "GetTexture", null));
}
}
}

View File

@ -50,9 +50,9 @@ namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
TestHelpers.InMethod();
// Overkill - we only really need the asset service, not a whole scene.
Scene scene = SceneHelpers.SetupScene();
Scene scene = new SceneHelpers().SetupScene();
GetTextureHandler handler = new GetTextureHandler(null, scene.AssetService);
GetTextureHandler handler = new GetTextureHandler(null, scene.AssetService, "TestGetTexture", null);
TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse();
req.Url = new Uri("http://localhost/?texture_id=00000000-0000-1111-9999-000000000012");

View File

@ -85,8 +85,8 @@ namespace OpenSim.Capabilities.Handlers
uploader.OnUpLoad += BakedTextureUploaded;
m_HostCapsObj.HttpListener.AddStreamHandler(
new BinaryStreamHandler("POST", capsBase + uploaderPath,
uploader.uploaderCaps));
new BinaryStreamHandler(
"POST", capsBase + uploaderPath, uploader.uploaderCaps, "UploadBakedTexture", null));
string protocol = "http://";

View File

@ -156,11 +156,12 @@ namespace OpenSim.Capabilities.Handlers
inv.Folders = new List<InventoryFolderBase>();
inv.Items = new List<InventoryItemBase>();
int version = 0;
int descendents = 0;
inv
= Fetch(
invFetch.owner_id, invFetch.folder_id, invFetch.owner_id,
invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version);
invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents);
if (inv.Folders != null)
{
@ -168,6 +169,8 @@ namespace OpenSim.Capabilities.Handlers
{
contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
}
descendents += inv.Folders.Count;
}
if (inv.Items != null)
@ -178,7 +181,7 @@ namespace OpenSim.Capabilities.Handlers
}
}
contents.descendents = contents.items.Array.Count + contents.categories.Array.Count;
contents.descendents = descendents;
contents.version = version;
// m_log.DebugFormat(
@ -206,7 +209,7 @@ namespace OpenSim.Capabilities.Handlers
/// <returns>An empty InventoryCollection if the inventory look up failed</returns>
private InventoryCollection Fetch(
UUID agentID, UUID folderID, UUID ownerID,
bool fetchFolders, bool fetchItems, int sortOrder, out int version)
bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents)
{
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
@ -215,6 +218,8 @@ namespace OpenSim.Capabilities.Handlers
// FIXME MAYBE: We're not handling sortOrder!
version = 0;
descendents = 0;
InventoryFolderImpl fold;
if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner)
{
@ -223,6 +228,7 @@ namespace OpenSim.Capabilities.Handlers
InventoryCollection ret = new InventoryCollection();
ret.Folders = new List<InventoryFolderBase>();
ret.Items = fold.RequestListOfItems();
descendents = ret.Folders.Count + ret.Items.Count;
return ret;
}
@ -246,24 +252,72 @@ namespace OpenSim.Capabilities.Handlers
version = containingFolder.Version;
// if (fetchItems)
if (fetchItems)
{
List<InventoryItemBase> itemsToReturn = contents.Items;
List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn);
// descendents must only include the links, not the linked items we add
descendents = originalItems.Count;
// Add target items for links in this folder before the links themselves.
foreach (InventoryItemBase item in originalItems)
{
if (item.AssetType == (int)AssetType.Link)
{
InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
// Take care of genuinely broken links where the target doesn't exist
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
// rather than having to keep track of every folder requested in the recursion.
if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
itemsToReturn.Insert(0, linkedItem);
}
}
// Now scan for folder links and insert the items they target and those links at the head of the return data
foreach (InventoryItemBase item in originalItems)
{
if (item.AssetType == (int)AssetType.LinkFolder)
{
InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID);
List<InventoryItemBase> links = linkedFolderContents.Items;
itemsToReturn.InsertRange(0, links);
foreach (InventoryItemBase link in linkedFolderContents.Items)
{
// Take care of genuinely broken links where the target doesn't exist
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
// rather than having to keep track of every folder requested in the recursion.
if (link != null)
{
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}",
// link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name);
InventoryItemBase linkedItem
= m_InventoryService.GetItem(new InventoryItemBase(link.AssetID));
if (linkedItem != null)
itemsToReturn.Insert(0, linkedItem);
}
}
}
}
}
// foreach (InventoryItemBase item in contents.Items)
// {
// List<InventoryItemBase> linkedItemsToAdd = new List<InventoryItemBase>();
//
// foreach (InventoryItemBase item in contents.Items)
// {
// if (item.AssetType == (int)AssetType.Link)
// {
// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
//
// // Take care of genuinely broken links where the target doesn't exist
// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
// // rather than having to keep track of every folder requested in the recursion.
// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
// linkedItemsToAdd.Insert(0, linkedItem);
// }
// }
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}",
// item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID);
// }
// =====
//
// foreach (InventoryItemBase linkedItem in linkedItemsToAdd)
// {
@ -340,12 +394,8 @@ namespace OpenSim.Capabilities.Handlers
llsdFolder.folder_id = invFolder.ID;
llsdFolder.parent_id = invFolder.ParentID;
llsdFolder.name = invFolder.Name;
if (invFolder.Type == (short)AssetType.Unknown || !Enum.IsDefined(typeof(AssetType), (sbyte)invFolder.Type))
llsdFolder.type = "-1";
else
llsdFolder.type = Utils.AssetTypeToString((AssetType)invFolder.Type);
llsdFolder.preferred_type = "-1";
llsdFolder.type = invFolder.Type;
llsdFolder.preferred_type = -1;
return llsdFolder;
}
@ -365,18 +415,8 @@ namespace OpenSim.Capabilities.Handlers
llsdItem.item_id = invItem.ID;
llsdItem.name = invItem.Name;
llsdItem.parent_id = invItem.Folder;
try
{
llsdItem.type = Utils.AssetTypeToString((AssetType)invItem.AssetType);
llsdItem.inv_type = Utils.InventoryTypeToString((InventoryType)invItem.InvType);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[WEB FETCH INV DESC HANDLER]: Problem setting asset {0} inventory {1} types while converting inventory item {2}: {3}",
invItem.AssetType, invItem.InvType, invItem.Name, e.Message);
}
llsdItem.type = invItem.AssetType;
llsdItem.inv_type = invItem.InvType;
llsdItem.permissions = new LLSDPermissions();
llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
@ -390,21 +430,7 @@ namespace OpenSim.Capabilities.Handlers
llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
llsdItem.sale_info = new LLSDSaleInfo();
llsdItem.sale_info.sale_price = invItem.SalePrice;
switch (invItem.SaleType)
{
default:
llsdItem.sale_info.sale_type = "not";
break;
case 1:
llsdItem.sale_info.sale_type = "original";
break;
case 2:
llsdItem.sale_info.sale_type = "copy";
break;
case 3:
llsdItem.sale_info.sale_type = "contents";
break;
}
llsdItem.sale_info.sale_type = invItem.SaleType;
return llsdItem;
}

View File

@ -68,7 +68,13 @@ namespace OpenSim.Capabilities.Handlers
ServerUtils.LoadPlugin<ILibraryService>(libService, args);
WebFetchInvDescHandler webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
IRequestHandler reqHandler = new RestStreamHandler("POST", "/CAPS/WebFetchInvDesc/" /*+ UUID.Random()*/, webFetchHandler.FetchInventoryDescendentsRequest);
IRequestHandler reqHandler
= new RestStreamHandler(
"POST",
"/CAPS/WebFetchInvDesc/" /*+ UUID.Random()*/,
webFetchHandler.FetchInventoryDescendentsRequest,
"WebFetchInvDesc",
null);
server.AddStreamHandler(reqHandler);
}

View File

@ -35,7 +35,7 @@ namespace OpenSim.Framework.Capabilities
public UUID folder_id;
public UUID parent_id;
public string name;
public string type;
public string preferred_type;
public int type;
public int preferred_type;
}
}

View File

@ -37,8 +37,8 @@ namespace OpenSim.Framework.Capabilities
public UUID asset_id;
public UUID item_id;
public LLSDPermissions permissions;
public string type;
public string inv_type;
public int type;
public int inv_type;
public int flags;
public LLSDSaleInfo sale_info;
@ -65,7 +65,7 @@ namespace OpenSim.Framework.Capabilities
public class LLSDSaleInfo
{
public int sale_price;
public string sale_type;
public int sale_type;
}
[OSDMap]

View File

@ -39,7 +39,11 @@ namespace OpenSim.Framework.Capabilities
private LLSDMethod<TRequest, TResponse> m_method;
public LLSDStreamhandler(string httpMethod, string path, LLSDMethod<TRequest, TResponse> method)
: base(httpMethod, path)
: this(httpMethod, path, method, null, null) {}
public LLSDStreamhandler(
string httpMethod, string path, LLSDMethod<TRequest, TResponse> method, string name, string description)
: base(httpMethod, path, name, description)
{
m_method = method;
}
@ -62,9 +66,7 @@ namespace OpenSim.Framework.Capabilities
TResponse response = m_method(llsdRequest);
Encoding encoding = new UTF8Encoding(false);
return encoding.GetBytes(LLSDHelpers.SerialiseLLSDReply(response));
return Util.UTF8NoBomEncoding.GetBytes(LLSDHelpers.SerialiseLLSDReply(response));
}
}
}

View File

@ -50,7 +50,7 @@ namespace OpenSim.ConsoleClient
request.ContentType = "application/x-www-form-urlencoded";
byte[] buffer = new System.Text.ASCIIEncoding().GetBytes(data);
byte[] buffer = Encoding.ASCII.GetBytes(data);
int length = (int) buffer.Length;
request.ContentLength = length;

View File

@ -106,7 +106,22 @@ namespace OpenSim.Data
/// <returns>true if the delete was successful, false if it was not</returns>
bool DeleteItems(string[] fields, string[] vals);
bool MoveItem(string id, string newParent);
/// <summary>
/// Move an item to another folder.
/// </summary>
/// <returns>/returns>
/// <param name='id'>UUID of the item</param>
/// <param name='newParent'>UUID of the new parent folder.</param>
bool MoveItem(string id, string newParentFolderID);
/// <summary>
/// Move a folder to another folder.
/// </summary>
/// <returns>/returns>
/// <param name='id'>UUID of the item</param>
/// <param name='newParent'>UUID of the new parent folder.</param>
bool MoveFolder(string id, string newParentFolderID);
XInventoryItem[] GetActiveGestures(UUID principalID);
int GetAssetPermissions(UUID principalID, UUID assetID);
}

View File

@ -89,5 +89,11 @@ namespace OpenSim.Data.MSSQL
return DoQuery(cmd);
}
}
public FriendsData[] GetFriends(Guid principalID)
{
return GetFriends(principalID.ToString());
}
}
}

View File

@ -813,7 +813,7 @@ namespace OpenSim.Data.MSSQL
{
try
{
using (SqlCommand command = new SqlCommand("DELETE FROM inventoryfolders WHERE folderID=@folderID", connection))
using (SqlCommand command = new SqlCommand("DELETE FROM inventoryfolders WHERE folderID=@folderID and type=-1", connection))
{
command.Parameters.Add(database.CreateParameter("folderID", folderID));

View File

@ -675,7 +675,7 @@ VALUES
cmd.ExecuteNonQuery();
}
sql = "INSERT INTO [landaccesslist] ([LandUUID],[AccessUUID],[Flags]) VALUES (@LandUUID,@AccessUUID,@Flags)";
sql = "INSERT INTO [landaccesslist] ([LandUUID],[AccessUUID],[Flags],[Expires]) VALUES (@LandUUID,@AccessUUID,@Flags,@Expires)";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
@ -1215,6 +1215,8 @@ VALUES
//Store new values
StoreNewRegionSettings(regionSettings);
LoadSpawnPoints(regionSettings);
return regionSettings;
}
@ -1252,7 +1254,7 @@ VALUES
,[elevation_1_ne] = @elevation_1_ne ,[elevation_2_ne] = @elevation_2_ne ,[elevation_1_se] = @elevation_1_se ,[elevation_2_se] = @elevation_2_se
,[elevation_1_sw] = @elevation_1_sw ,[elevation_2_sw] = @elevation_2_sw ,[water_height] = @water_height ,[terrain_raise_limit] = @terrain_raise_limit
,[terrain_lower_limit] = @terrain_lower_limit ,[use_estate_sun] = @use_estate_sun ,[fixed_sun] = @fixed_sun ,[sun_position] = @sun_position
,[covenant] = @covenant ,[covenant_datetime] = @covenant_datetime, [sunvectorx] = @sunvectorx, [sunvectory] = @sunvectory, [sunvectorz] = @sunvectorz, [Sandbox] = @Sandbox, [loaded_creation_datetime] = @loaded_creation_datetime, [loaded_creation_id] = @loaded_creation_id
,[covenant] = @covenant ,[covenant_datetime] = @covenant_datetime, [sunvectorx] = @sunvectorx, [sunvectory] = @sunvectory, [sunvectorz] = @sunvectorz, [Sandbox] = @Sandbox, [loaded_creation_datetime] = @loaded_creation_datetime, [loaded_creation_id] = @loaded_creation_id, [map_tile_id] = @TerrainImageID, [telehubobject] = @telehubobject, [parcel_tile_id] = @ParcelImageID
WHERE [regionUUID] = @regionUUID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
@ -1263,6 +1265,7 @@ VALUES
cmd.ExecuteNonQuery();
}
}
SaveSpawnPoints(regionSettings);
}
public void Shutdown()
@ -1383,6 +1386,11 @@ VALUES
newSettings.LoadedCreationID = "";
else
newSettings.LoadedCreationID = (String)row["loaded_creation_id"];
newSettings.TerrainImageID = new UUID((string)row["map_tile_ID"]);
newSettings.ParcelImageID = new UUID((Guid)row["parcel_tile_ID"]);
newSettings.TelehubObject = new UUID((Guid)row["TelehubObject"]);
return newSettings;
}
@ -1454,6 +1462,13 @@ VALUES
}
newData.ParcelAccessList = new List<LandAccessEntry>();
newData.MediaDescription = (string)row["MediaDescription"];
newData.MediaType = (string)row["MediaType"];
newData.MediaWidth = Convert.ToInt32((((string)row["MediaSize"]).Split(','))[0]);
newData.MediaHeight = Convert.ToInt32((((string)row["MediaSize"]).Split(','))[1]);
newData.MediaLoop = Convert.ToBoolean(row["MediaLoop"]);
newData.ObscureMusic = Convert.ToBoolean(row["ObscureMusic"]);
newData.ObscureMedia = Convert.ToBoolean(row["ObscureMedia"]);
return newData;
}
@ -1468,7 +1483,7 @@ VALUES
LandAccessEntry entry = new LandAccessEntry();
entry.AgentID = new UUID((Guid)row["AccessUUID"]);
entry.Flags = (AccessList)Convert.ToInt32(row["Flags"]);
entry.Expires = 0;
entry.Expires = Convert.ToInt32(row["Expires"]);
return entry;
}
@ -1497,7 +1512,8 @@ VALUES
prim.TouchName = (string)primRow["TouchName"];
// permissions
prim.Flags = (PrimFlags)Convert.ToUInt32(primRow["ObjectFlags"]);
prim.CreatorID = new UUID((Guid)primRow["CreatorID"]);
//prim.CreatorID = new UUID((Guid)primRow["CreatorID"]);
prim.CreatorIdentification = (string)primRow["CreatorID"];
prim.OwnerID = new UUID((Guid)primRow["OwnerID"]);
prim.GroupID = new UUID((Guid)primRow["GroupID"]);
prim.LastOwnerID = new UUID((Guid)primRow["LastOwnerID"]);
@ -1691,7 +1707,8 @@ VALUES
taskItem.Name = (string)inventoryRow["name"];
taskItem.Description = (string)inventoryRow["description"];
taskItem.CreationDate = Convert.ToUInt32(inventoryRow["creationDate"]);
taskItem.CreatorID = new UUID((Guid)inventoryRow["creatorID"]);
//taskItem.CreatorID = new UUID((Guid)inventoryRow["creatorID"]);
taskItem.CreatorIdentification = (string)inventoryRow["creatorID"];
taskItem.OwnerID = new UUID((Guid)inventoryRow["ownerID"]);
taskItem.LastOwnerID = new UUID((Guid)inventoryRow["lastOwnerID"]);
taskItem.GroupID = new UUID((Guid)inventoryRow["groupID"]);
@ -1792,6 +1809,9 @@ VALUES
parameters.Add(_Database.CreateParameter("covenant_datetime", settings.CovenantChangedDateTime));
parameters.Add(_Database.CreateParameter("Loaded_Creation_DateTime", settings.LoadedCreationDateTime));
parameters.Add(_Database.CreateParameter("Loaded_Creation_ID", settings.LoadedCreationID));
parameters.Add(_Database.CreateParameter("TerrainImageID", settings.TerrainImageID));
parameters.Add(_Database.CreateParameter("ParcelImageID", settings.ParcelImageID));
parameters.Add(_Database.CreateParameter("TelehubObject", settings.TelehubObject));
return parameters.ToArray();
}
@ -1859,6 +1879,7 @@ VALUES
parameters.Add(_Database.CreateParameter("LandUUID", parcelID));
parameters.Add(_Database.CreateParameter("AccessUUID", parcelAccessEntry.AgentID));
parameters.Add(_Database.CreateParameter("Flags", parcelAccessEntry.Flags));
parameters.Add(_Database.CreateParameter("Expires", parcelAccessEntry.Expires));
return parameters.ToArray();
}
@ -2063,5 +2084,57 @@ VALUES
#endregion
#endregion
private void LoadSpawnPoints(RegionSettings rs)
{
rs.ClearSpawnPoints();
string sql = "SELECT Yaw, Pitch, Distance FROM spawn_points WHERE RegionUUID = @RegionUUID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", rs.RegionUUID.ToString()));
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
SpawnPoint sp = new SpawnPoint();
sp.Yaw = (float)reader["Yaw"];
sp.Pitch = (float)reader["Pitch"];
sp.Distance = (float)reader["Distance"];
rs.AddSpawnPoint(sp);
}
}
}
}
private void SaveSpawnPoints(RegionSettings rs)
{
string sql = "DELETE FROM spawn_points WHERE RegionUUID = @RegionUUID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", rs.RegionUUID));
conn.Open();
cmd.ExecuteNonQuery();
}
foreach (SpawnPoint p in rs.SpawnPoints())
{
sql = "INSERT INTO spawn_points (RegionUUID, Yaw, Pitch, Distance) VALUES (@RegionUUID, @Yaw, @Pitch, @Distance)";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", rs.RegionUUID));
cmd.Parameters.Add(_Database.CreateParameter("@Yaw", p.Yaw));
cmd.Parameters.Add(_Database.CreateParameter("@Pitch", p.Pitch));
cmd.Parameters.Add(_Database.CreateParameter("@Distance", p.Distance));
conn.Open();
cmd.ExecuteNonQuery();
}
}
}
}
}

View File

@ -43,12 +43,12 @@ namespace OpenSim.Data.MSSQL
// private static readonly ILog m_log = LogManager.GetLogger(
// MethodBase.GetCurrentMethod().DeclaringType);
private MSSQLGenericTableHandler<XInventoryFolder> m_Folders;
private MSSQLFolderHandler m_Folders;
private MSSQLItemHandler m_Items;
public MSSQLXInventoryData(string conn, string realm)
{
m_Folders = new MSSQLGenericTableHandler<XInventoryFolder>(
m_Folders = new MSSQLFolderHandler(
conn, "inventoryfolders", "InventoryStore");
m_Items = new MSSQLItemHandler(
conn, "inventoryitems", String.Empty);
@ -85,6 +85,7 @@ namespace OpenSim.Data.MSSQL
{
return m_Folders.Delete(field, val);
}
public bool DeleteFolders(string[] fields, string[] vals)
{
return m_Folders.Delete(fields, vals);
@ -94,15 +95,22 @@ namespace OpenSim.Data.MSSQL
{
return m_Items.Delete(field, val);
}
public bool DeleteItems(string[] fields, string[] vals)
{
return m_Items.Delete(fields, vals);
}
public bool MoveItem(string id, string newParent)
{
return m_Items.MoveItem(id, newParent);
}
public bool MoveFolder(string id, string newParent)
{
return m_Folders.MoveFolder(id, newParent);
}
public XInventoryItem[] GetActiveGestures(UUID principalID)
{
return m_Items.GetActiveGestures(principalID);
@ -124,79 +132,115 @@ namespace OpenSim.Data.MSSQL
public bool MoveItem(string id, string newParent)
{
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand())
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = String.Format("update {0} set parentFolderID = @ParentFolderID where inventoryID = @InventoryID", m_Realm);
cmd.Parameters.Add(m_database.CreateParameter("@ParentFolderID", newParent));
cmd.Parameters.Add(m_database.CreateParameter("@InventoryID", id));
cmd.Connection = conn;
conn.Open();
return cmd.ExecuteNonQuery() == 0 ? false : true;
cmd.CommandText = String.Format("update {0} set parentFolderID = @ParentFolderID where inventoryID = @InventoryID", m_Realm);
cmd.Parameters.Add(m_database.CreateParameter("@ParentFolderID", newParent));
cmd.Parameters.Add(m_database.CreateParameter("@InventoryID", id));
cmd.Connection = conn;
conn.Open();
return cmd.ExecuteNonQuery() == 0 ? false : true;
}
}
}
public XInventoryItem[] GetActiveGestures(UUID principalID)
{
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = String.Format("select * from inventoryitems where avatarId = @uuid and assetType = @type and flags = 1", m_Realm);
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = String.Format("select * from inventoryitems where avatarId = @uuid and assetType = @type and flags = 1", m_Realm);
cmd.Parameters.Add(m_database.CreateParameter("@uuid", principalID.ToString()));
cmd.Parameters.Add(m_database.CreateParameter("@type", (int)AssetType.Gesture));
cmd.Connection = conn;
conn.Open();
return DoQuery(cmd);
cmd.Parameters.Add(m_database.CreateParameter("@uuid", principalID.ToString()));
cmd.Parameters.Add(m_database.CreateParameter("@type", (int)AssetType.Gesture));
cmd.Connection = conn;
conn.Open();
return DoQuery(cmd);
}
}
}
public int GetAssetPermissions(UUID principalID, UUID assetID)
{
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = String.Format("select bit_or(inventoryCurrentPermissions) as inventoryCurrentPermissions from inventoryitems where avatarID = @PrincipalID and assetID = @AssetID group by assetID", m_Realm);
cmd.Parameters.Add(m_database.CreateParameter("@PrincipalID", principalID.ToString()));
cmd.Parameters.Add(m_database.CreateParameter("@AssetID", assetID.ToString()));
cmd.Connection = conn;
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
using (SqlCommand cmd = new SqlCommand())
{
int perms = 0;
if (reader.Read())
cmd.CommandText = String.Format("select bit_or(inventoryCurrentPermissions) as inventoryCurrentPermissions from inventoryitems where avatarID = @PrincipalID and assetID = @AssetID group by assetID", m_Realm);
cmd.Parameters.Add(m_database.CreateParameter("@PrincipalID", principalID.ToString()));
cmd.Parameters.Add(m_database.CreateParameter("@AssetID", assetID.ToString()));
cmd.Connection = conn;
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
perms = Convert.ToInt32(reader["inventoryCurrentPermissions"]);
int perms = 0;
if (reader.Read())
{
perms = Convert.ToInt32(reader["inventoryCurrentPermissions"]);
}
return perms;
}
return perms;
}
}
}
public override bool Store(XInventoryItem item)
{
if (!base.Store(item))
return false;
string sql = "update inventoryfolders set version=version+1 where folderID = @folderID";
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
conn.Open();
cmd.Parameters.AddWithValue("@folderID", item.parentFolderID.ToString());
try
{
cmd.ExecuteNonQuery();
}
catch (Exception)
{
return false;
}
cmd.Parameters.AddWithValue("@folderID", item.parentFolderID.ToString());
try
{
cmd.ExecuteNonQuery();
}
catch (Exception)
{
return false;
}
}
return true;
}
}
}
public class MSSQLFolderHandler : MSSQLGenericTableHandler<XInventoryFolder>
{
public MSSQLFolderHandler(string c, string t, string m) :
base(c, t, m)
{
}
public bool MoveFolder(string id, string newParentFolderID)
{
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = String.Format("update {0} set parentFolderID = @ParentFolderID where folderID = @folderID", m_Realm);
cmd.Parameters.Add(m_database.CreateParameter("@ParentFolderID", newParentFolderID));
cmd.Parameters.Add(m_database.CreateParameter("@folderID", id));
cmd.Connection = conn;
conn.Open();
return cmd.ExecuteNonQuery() == 0 ? false : true;
}
}
return true;
}
}
}

View File

@ -1044,10 +1044,93 @@ ALTER TABLE primitems ALTER COLUMN CreatorID uniqueidentifier NOT NULL
COMMIT
:VERSION 29 #---------------------
:VERSION 29 #----------------- Region Covenant changed time
BEGIN TRANSACTION
ALTER TABLE regionsettings ADD covenant_datetime int NOT NULL default 0
COMMIT
:VERSION 30 #------------------Migrate creatorID storage to varchars instead of UUIDs for HG support
BEGIN TRANSACTION
EXECUTE sp_rename N'dbo.prims.creatorid', N'creatoridold', 'COLUMN'
EXECUTE sp_rename N'dbo.primitems.creatorid', N'creatoridold', 'COLUMN'
COMMIT
:VERSION 31 #---------------------
BEGIN TRANSACTION
ALTER TABLE prims ADD CreatorID varchar(255)
ALTER TABLE primitems ADD CreatorID varchar(255)
COMMIT
:VERSION 32 #---------------------
BEGIN TRANSACTION
UPDATE prims SET prims.CreatorID = CONVERT(varchar(255), creatoridold)
UPDATE primitems SET primitems.CreatorID = CONVERT(varchar(255), creatoridold)
COMMIT
:VERSION 33 #---------------------
BEGIN TRANSACTION
ALTER TABLE prims
ADD CONSTRAINT DF_prims_CreatorIDNew
DEFAULT '00000000-0000-0000-0000-000000000000'
FOR CreatorID
ALTER TABLE prims ALTER COLUMN CreatorID varchar(255) NOT NULL
ALTER TABLE primitems
ADD CONSTRAINT DF_primitems_CreatorIDNew
DEFAULT '00000000-0000-0000-0000-000000000000'
FOR CreatorID
ALTER TABLE primitems ALTER COLUMN CreatorID varchar(255) NOT NULL
COMMIT
:VERSION 34 #--------------- Telehub support
BEGIN TRANSACTION
CREATE TABLE [dbo].[Spawn_Points](
[RegionUUID] [uniqueidentifier] NOT NULL,
[Yaw] [float] NOT NULL,
[Pitch] [float] NOT NULL,
[Distance] [float] NOT NULL,
PRIMARY KEY CLUSTERED
(
[RegionUUID] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE regionsettings ADD TelehubObject uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
COMMIT
:VERSION 35 #---------------- Parcels for sale
BEGIN TRANSACTION
ALTER TABLE regionsettings ADD parcel_tile_ID uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
COMMIT
:VERSION 36 #---------------- Timed bans/access
BEGIN TRANSACTION
ALTER TABLE landaccesslist ADD Expires integer NOT NULL DEFAULT 0;
COMMIT

View File

@ -217,6 +217,8 @@ namespace OpenSim.Data.MySQL
public virtual bool Store(T row)
{
// m_log.DebugFormat("[MYSQL GENERIC TABLE HANDLER]: Store(T row) invoked");
using (MySqlCommand cmd = new MySqlCommand())
{
string query = "";
@ -271,6 +273,10 @@ namespace OpenSim.Data.MySQL
public virtual bool Delete(string[] fields, string[] keys)
{
// m_log.DebugFormat(
// "[MYSQL GENERIC TABLE HANDLER]: Delete(string[] fields, string[] keys) invoked with {0}:{1}",
// string.Join(",", fields), string.Join(",", keys));
if (fields.Length != keys.Length)
return false;

View File

@ -26,9 +26,10 @@
*/
using System;
using System.Data;
using System.Reflection;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using log4net;
using MySql.Data.MySqlClient;
using OpenMetaverse;
@ -41,12 +42,12 @@ namespace OpenSim.Data.MySQL
/// </summary>
public class MySQLXInventoryData : IXInventoryData
{
private MySQLGenericTableHandler<XInventoryFolder> m_Folders;
private MySqlFolderHandler m_Folders;
private MySqlItemHandler m_Items;
public MySQLXInventoryData(string conn, string realm)
{
m_Folders = new MySQLGenericTableHandler<XInventoryFolder>(
m_Folders = new MySqlFolderHandler(
conn, "inventoryfolders", "InventoryStore");
m_Items = new MySqlItemHandler(
conn, "inventoryitems", String.Empty);
@ -105,6 +106,11 @@ namespace OpenSim.Data.MySQL
return m_Items.MoveItem(id, newParent);
}
public bool MoveFolder(string id, string newParent)
{
return m_Folders.MoveFolder(id, newParent);
}
public XInventoryItem[] GetActiveGestures(UUID principalID)
{
return m_Items.GetActiveGestures(principalID);
@ -118,22 +124,69 @@ namespace OpenSim.Data.MySQL
public class MySqlItemHandler : MySQLGenericTableHandler<XInventoryItem>
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public MySqlItemHandler(string c, string t, string m) :
base(c, t, m)
{
}
public override bool Delete(string field, string val)
{
XInventoryItem[] retrievedItems = Get(new string[] { field }, new string[] { val });
if (retrievedItems.Length == 0)
return false;
if (!base.Delete(field, val))
return false;
// Don't increment folder version here since Delete(string, string) calls Delete(string[], string[])
// IncrementFolderVersion(retrievedItems[0].parentFolderID);
return true;
}
public override bool Delete(string[] fields, string[] vals)
{
XInventoryItem[] retrievedItems = Get(fields, vals);
if (retrievedItems.Length == 0)
return false;
if (!base.Delete(fields, vals))
return false;
HashSet<UUID> deletedItemFolderUUIDs = new HashSet<UUID>();
Array.ForEach<XInventoryItem>(retrievedItems, i => deletedItemFolderUUIDs.Add(i.parentFolderID));
foreach (UUID deletedItemFolderUUID in deletedItemFolderUUIDs)
IncrementFolderVersion(deletedItemFolderUUID);
return true;
}
public bool MoveItem(string id, string newParent)
{
XInventoryItem[] retrievedItems = Get(new string[] { "inventoryID" }, new string[] { id });
if (retrievedItems.Length == 0)
return false;
UUID oldParent = retrievedItems[0].parentFolderID;
using (MySqlCommand cmd = new MySqlCommand())
{
cmd.CommandText = String.Format("update {0} set parentFolderID = ?ParentFolderID where inventoryID = ?InventoryID", m_Realm);
cmd.Parameters.AddWithValue("?ParentFolderID", newParent);
cmd.Parameters.AddWithValue("?InventoryID", id);
return ExecuteNonQuery(cmd) == 0 ? false : true;
if (ExecuteNonQuery(cmd) == 0)
return false;
}
IncrementFolderVersion(oldParent);
IncrementFolderVersion(newParent);
return true;
}
public XInventoryItem[] GetActiveGestures(UUID principalID)
@ -184,6 +237,21 @@ namespace OpenSim.Data.MySQL
if (!base.Store(item))
return false;
IncrementFolderVersion(item.parentFolderID);
return true;
}
private bool IncrementFolderVersion(UUID folderID)
{
return IncrementFolderVersion(folderID.ToString());
}
private bool IncrementFolderVersion(string folderID)
{
// m_log.DebugFormat("[MYSQL ITEM HANDLER]: Incrementing version on folder {0}", folderID);
// Util.PrintCallStack();
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
@ -193,7 +261,7 @@ namespace OpenSim.Data.MySQL
cmd.Connection = dbcon;
cmd.CommandText = String.Format("update inventoryfolders set version=version+1 where folderID = ?folderID");
cmd.Parameters.AddWithValue("?folderID", item.parentFolderID.ToString());
cmd.Parameters.AddWithValue("?folderID", folderID);
try
{
@ -205,8 +273,95 @@ namespace OpenSim.Data.MySQL
}
cmd.Dispose();
}
dbcon.Close();
}
return true;
}
}
public class MySqlFolderHandler : MySQLGenericTableHandler<XInventoryFolder>
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public MySqlFolderHandler(string c, string t, string m) :
base(c, t, m)
{
}
public bool MoveFolder(string id, string newParentFolderID)
{
XInventoryFolder[] folders = Get(new string[] { "folderID" }, new string[] { id });
if (folders.Length == 0)
return false;
UUID oldParentFolderUUID = folders[0].parentFolderID;
using (MySqlCommand cmd = new MySqlCommand())
{
cmd.CommandText
= String.Format(
"update {0} set parentFolderID = ?ParentFolderID where folderID = ?folderID", m_Realm);
cmd.Parameters.AddWithValue("?ParentFolderID", newParentFolderID);
cmd.Parameters.AddWithValue("?folderID", id);
if (ExecuteNonQuery(cmd) == 0)
return false;
}
IncrementFolderVersion(oldParentFolderUUID);
IncrementFolderVersion(newParentFolderID);
return true;
}
public override bool Store(XInventoryFolder folder)
{
if (!base.Store(folder))
return false;
IncrementFolderVersion(folder.parentFolderID);
return true;
}
private bool IncrementFolderVersion(UUID folderID)
{
return IncrementFolderVersion(folderID.ToString());
}
private bool IncrementFolderVersion(string folderID)
{
// m_log.DebugFormat("[MYSQL FOLDER HANDLER]: Incrementing version on folder {0}", folderID);
// Util.PrintCallStack();
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand())
{
cmd.Connection = dbcon;
cmd.CommandText = String.Format("update inventoryfolders set version=version+1 where folderID = ?folderID");
cmd.Parameters.AddWithValue("?folderID", folderID);
try
{
cmd.ExecuteNonQuery();
}
catch (Exception)
{
return false;
}
cmd.Dispose();
}
dbcon.Close();
}
return true;
}
}

View File

@ -28,6 +28,9 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using log4net;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Data;
@ -36,12 +39,26 @@ namespace OpenSim.Data.Null
{
public class NullFriendsData : IFriendsData
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static List<FriendsData> m_Data = new List<FriendsData>();
public NullFriendsData(string connectionString, string realm)
{
}
/// <summary>
/// Clear all friends data
/// </summary>
/// <remarks>
/// This is required by unit tests to clear the static data between test runs.
/// </remarks>
public static void Clear()
{
lock (m_Data)
m_Data.Clear();
}
public FriendsData[] GetFriends(UUID principalID)
{
return GetFriends(principalID.ToString());
@ -56,20 +73,30 @@ namespace OpenSim.Data.Null
/// <returns></returns>
public FriendsData[] GetFriends(string userID)
{
List<FriendsData> lst = m_Data.FindAll(fdata =>
lock (m_Data)
{
return fdata.PrincipalID == userID.ToString();
});
if (lst != null)
{
lst.ForEach(f =>
List<FriendsData> lst = m_Data.FindAll(fdata =>
{
FriendsData f2 = m_Data.Find(candidateF2 => f.Friend == candidateF2.PrincipalID);
if (f2 != null) { f.Data["TheirFlags"] = f2.Data["Flags"]; }
return fdata.PrincipalID == userID.ToString();
});
return lst.ToArray();
if (lst != null)
{
lst.ForEach(f =>
{
FriendsData f2 = m_Data.Find(candidateF2 => f.Friend == candidateF2.PrincipalID);
if (f2 != null)
f.Data["TheirFlags"] = f2.Data["Flags"];
// m_log.DebugFormat(
// "[NULL FRIENDS DATA]: Got {0} {1} {2} for {3}",
// f.Friend, f.Data["Flags"], f2 != null ? f.Data["TheirFlags"] : "not found!", f.PrincipalID);
});
// m_log.DebugFormat("[NULL FRIENDS DATA]: Got {0} friends for {1}", lst.Count, userID);
return lst.ToArray();
}
}
return new FriendsData[0];
@ -80,7 +107,11 @@ namespace OpenSim.Data.Null
if (data == null)
return false;
m_Data.Add(data);
// m_log.DebugFormat(
// "[NULL FRIENDS DATA]: Storing {0} {1} {2}", data.PrincipalID, data.Friend, data.Data["Flags"]);
lock (m_Data)
m_Data.Add(data);
return true;
}
@ -92,14 +123,21 @@ namespace OpenSim.Data.Null
public bool Delete(string userID, string friendID)
{
List<FriendsData> lst = m_Data.FindAll(delegate(FriendsData fdata) { return fdata.PrincipalID == userID.ToString(); });
if (lst != null)
lock (m_Data)
{
FriendsData friend = lst.Find(delegate(FriendsData fdata) { return fdata.Friend == friendID; });
if (friendID != null)
List<FriendsData> lst = m_Data.FindAll(delegate(FriendsData fdata) { return fdata.PrincipalID == userID.ToString(); });
if (lst != null)
{
m_Data.Remove(friend);
return true;
FriendsData friend = lst.Find(delegate(FriendsData fdata) { return fdata.Friend == friendID; });
if (friendID != null)
{
// m_log.DebugFormat(
// "[NULL FRIENDS DATA]: Deleting friend {0} {1} for {2}",
// friend.Friend, friend.Data["Flags"], friend.PrincipalID);
m_Data.Remove(friend);
return true;
}
}
}

View File

@ -110,7 +110,6 @@ namespace OpenSim.Data.Null
return false;
}
public PresenceData[] Get(string field, string data)
{
if (Instance != this)

View File

@ -47,7 +47,7 @@ namespace OpenSim.Data.SQLite
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private SQLiteGenericTableHandler<XInventoryFolder> m_Folders;
private SqliteFolderHandler m_Folders;
private SqliteItemHandler m_Items;
public SQLiteXInventoryData(string conn, string realm)
@ -55,7 +55,7 @@ namespace OpenSim.Data.SQLite
if (Util.IsWindows())
Util.LoadArchSpecificWindowsDll("sqlite3.dll");
m_Folders = new SQLiteGenericTableHandler<XInventoryFolder>(
m_Folders = new SqliteFolderHandler(
conn, "inventoryfolders", "XInventoryStore");
m_Items = new SqliteItemHandler(
conn, "inventoryitems", String.Empty);
@ -114,6 +114,11 @@ namespace OpenSim.Data.SQLite
return m_Items.MoveItem(id, newParent);
}
public bool MoveFolder(string id, string newParent)
{
return m_Folders.MoveFolder(id, newParent);
}
public XInventoryItem[] GetActiveGestures(UUID principalID)
{
return m_Items.GetActiveGestures(principalID);
@ -177,4 +182,23 @@ namespace OpenSim.Data.SQLite
return perms;
}
}
public class SqliteFolderHandler : SQLiteGenericTableHandler<XInventoryFolder>
{
public SqliteFolderHandler(string c, string t, string m) :
base(c, t, m)
{
}
public bool MoveFolder(string id, string newParentFolderID)
{
SqliteCommand cmd = new SqliteCommand();
cmd.CommandText = String.Format("update {0} set parentFolderID = :ParentFolderID where folderID = :FolderID", m_Realm);
cmd.Parameters.Add(new SqliteParameter(":ParentFolderID", newParentFolderID));
cmd.Parameters.Add(new SqliteParameter(":FolderID", id));
return ExecuteNonQuery(cmd, m_Connection) == 0 ? false : true;
}
}
}

View File

@ -1070,8 +1070,6 @@ namespace OpenSim.Data.Tests
regionInfo.RegionLocX = 0;
regionInfo.RegionLocY = 0;
Scene scene = new Scene(regionInfo);
SceneObjectPart sop = new SceneObjectPart();
sop.Name = name;
sop.Description = name;
@ -1082,7 +1080,7 @@ namespace OpenSim.Data.Tests
sop.Shape = PrimitiveBaseShape.Default;
SceneObjectGroup sog = new SceneObjectGroup(sop);
sog.SetScene(scene);
// sog.SetScene(scene);
return sog;
}

View File

@ -98,6 +98,11 @@ namespace OpenSim.Framework
/// </summary>
public string lastname;
/// <summary>
/// Agent's full name.
/// </summary>
public string Name { get { return string.Format("{0} {1}", firstname, lastname); } }
/// <summary>
/// Random Unique GUID for this session. Client gets this at login and it's
/// only supposed to be disclosed over secure channels

View File

@ -199,7 +199,14 @@ namespace OpenSim.Framework
//
public class Cache
{
/// <summary>
/// Must only be accessed under lock.
/// </summary>
private List<CacheItemBase> m_Index = new List<CacheItemBase>();
/// <summary>
/// Must only be accessed under m_Index lock.
/// </summary>
private Dictionary<string, CacheItemBase> m_Lookup =
new Dictionary<string, CacheItemBase>();
@ -320,19 +327,19 @@ namespace OpenSim.Framework
{
if (m_Lookup.ContainsKey(index))
item = m_Lookup[index];
}
if (item == null)
{
if (item == null)
{
Expire(true);
return null;
}
item.hits++;
item.lastUsed = DateTime.Now;
Expire(true);
return null;
}
item.hits++;
item.lastUsed = DateTime.Now;
Expire(true);
return item;
}
@ -385,7 +392,10 @@ namespace OpenSim.Framework
//
public Object Find(Predicate<CacheItemBase> d)
{
CacheItemBase item = m_Index.Find(d);
CacheItemBase item;
lock (m_Index)
item = m_Index.Find(d);
if (item == null)
return null;
@ -419,12 +429,12 @@ namespace OpenSim.Framework
public virtual void Store(string index, Object data, Type container,
Object[] parameters)
{
Expire(false);
CacheItemBase item;
lock (m_Index)
{
Expire(false);
if (m_Index.Contains(new CacheItemBase(index)))
{
if ((m_Flags & CacheFlags.AllowUpdate) != 0)
@ -450,9 +460,17 @@ namespace OpenSim.Framework
m_Index.Add(item);
m_Lookup[index] = item;
}
item.Store(data);
}
/// <summary>
/// Expire items as appropriate.
/// </summary>
/// <remarks>
/// Callers must lock m_Index.
/// </remarks>
/// <param name='getting'></param>
protected virtual void Expire(bool getting)
{
if (getting && (m_Strategy == CacheStrategy.Aggressive))
@ -475,12 +493,10 @@ namespace OpenSim.Framework
switch (m_Strategy)
{
case CacheStrategy.Aggressive:
if (Count < Size)
return;
case CacheStrategy.Aggressive:
if (Count < Size)
return;
lock (m_Index)
{
m_Index.Sort(new SortLRU());
m_Index.Reverse();
@ -490,7 +506,7 @@ namespace OpenSim.Framework
ExpireDelegate doExpire = OnExpire;
if (doExpire != null)
if (doExpire != null)
{
List<CacheItemBase> candidates =
m_Index.GetRange(target, Count - target);
@ -513,27 +529,34 @@ namespace OpenSim.Framework
foreach (CacheItemBase item in m_Index)
m_Lookup[item.uuid] = item;
}
}
break;
default:
break;
break;
default:
break;
}
}
public void Invalidate(string uuid)
{
if (!m_Lookup.ContainsKey(uuid))
return;
lock (m_Index)
{
if (!m_Lookup.ContainsKey(uuid))
return;
CacheItemBase item = m_Lookup[uuid];
m_Lookup.Remove(uuid);
m_Index.Remove(item);
CacheItemBase item = m_Lookup[uuid];
m_Lookup.Remove(uuid);
m_Index.Remove(item);
}
}
public void Clear()
{
m_Index.Clear();
m_Lookup.Clear();
lock (m_Index)
{
m_Index.Clear();
m_Lookup.Clear();
}
}
}
}

View File

@ -0,0 +1,40 @@
/*
* 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 OpenMetaverse;
using OpenSim.Framework;
namespace OpenSim.Framework.Client
{
public interface IClientInventory
{
void SendRemoveInventoryFolders(UUID[] folders);
void SendRemoveInventoryItems(UUID[] folders);
void SendBulkUpdateInventory(InventoryFolderBase[] folders, InventoryItemBase[] items);
}
}

View File

@ -29,6 +29,7 @@ using System;
using System.Xml;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
@ -40,6 +41,8 @@ namespace OpenSim.Framework.Console
{
public class Commands : ICommands
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// Encapsulates a command that can be invoked from the console
/// </summary>
@ -76,12 +79,23 @@ namespace OpenSim.Framework.Console
public List<CommandDelegate> fn;
}
public const string GeneralHelpText
= "To enter an argument that contains spaces, surround the argument with double quotes.\nFor example, show object name \"My long object name\"\n";
public const string ItemHelpText
= "For more information, type 'help <item>' where <item> is one of the following:";
/// <value>
/// Commands organized by keyword in a tree
/// </value>
private Dictionary<string, object> tree =
new Dictionary<string, object>();
/// <summary>
/// Commands organized by module
/// </summary>
private Dictionary<string, List<CommandInfo>> m_modulesCommands = new Dictionary<string, List<CommandInfo>>();
/// <summary>
/// Get help for the given help string
/// </summary>
@ -98,8 +112,10 @@ namespace OpenSim.Framework.Console
// General help
if (helpParts.Count == 0)
{
help.AddRange(CollectHelp(tree));
help.Sort();
help.Add(""); // Will become a newline.
help.Add(GeneralHelpText);
help.Add(ItemHelpText);
help.AddRange(CollectModulesHelp(tree));
}
else
{
@ -119,6 +135,13 @@ namespace OpenSim.Framework.Console
string originalHelpRequest = string.Join(" ", helpParts.ToArray());
List<string> help = new List<string>();
// Check modules first to see if we just need to display a list of those commands
if (TryCollectModuleHelp(originalHelpRequest, help))
{
help.Insert(0, ItemHelpText);
return help;
}
Dictionary<string, object> dict = tree;
while (helpParts.Count > 0)
{
@ -161,26 +184,64 @@ namespace OpenSim.Framework.Console
return help;
}
private List<string> CollectHelp(Dictionary<string, object> dict)
/// <summary>
/// Try to collect help for the given module if that module exists.
/// </summary>
/// <param name="moduleName"></param>
/// <param name="helpText">/param>
/// <returns>true if there was the module existed, false otherwise.</returns>
private bool TryCollectModuleHelp(string moduleName, List<string> helpText)
{
List<string> result = new List<string>();
foreach (KeyValuePair<string, object> kvp in dict)
lock (m_modulesCommands)
{
if (kvp.Value is Dictionary<string, Object>)
foreach (string key in m_modulesCommands.Keys)
{
result.AddRange(CollectHelp((Dictionary<string, Object>)kvp.Value));
}
else
{
if (((CommandInfo)kvp.Value).long_help != String.Empty)
result.Add(((CommandInfo)kvp.Value).help_text+" - "+
((CommandInfo)kvp.Value).long_help);
// Allow topic help requests to succeed whether they are upper or lowercase.
if (moduleName.ToLower() == key.ToLower())
{
List<CommandInfo> commands = m_modulesCommands[key];
var ourHelpText = commands.ConvertAll(c => string.Format("{0} - {1}", c.help_text, c.long_help));
ourHelpText.Sort();
helpText.AddRange(ourHelpText);
return true;
}
}
return false;
}
return result;
}
private List<string> CollectModulesHelp(Dictionary<string, object> dict)
{
lock (m_modulesCommands)
{
List<string> helpText = new List<string>(m_modulesCommands.Keys);
helpText.Sort();
return helpText;
}
}
// private List<string> CollectHelp(Dictionary<string, object> dict)
// {
// List<string> result = new List<string>();
//
// foreach (KeyValuePair<string, object> kvp in dict)
// {
// if (kvp.Value is Dictionary<string, Object>)
// {
// result.AddRange(CollectHelp((Dictionary<string, Object>)kvp.Value));
// }
// else
// {
// if (((CommandInfo)kvp.Value).long_help != String.Empty)
// result.Add(((CommandInfo)kvp.Value).help_text+" - "+
// ((CommandInfo)kvp.Value).long_help);
// }
// }
// return result;
// }
/// <summary>
/// Add a command to those which can be invoked from the console.
/// </summary>
@ -212,21 +273,19 @@ namespace OpenSim.Framework.Console
Dictionary<string, Object> current = tree;
foreach (string s in parts)
foreach (string part in parts)
{
if (current.ContainsKey(s))
if (current.ContainsKey(part))
{
if (current[s] is Dictionary<string, Object>)
{
current = (Dictionary<string, Object>)current[s];
}
if (current[part] is Dictionary<string, Object>)
current = (Dictionary<string, Object>)current[part];
else
return;
}
else
{
current[s] = new Dictionary<string, Object>();
current = (Dictionary<string, Object>)current[s];
current[part] = new Dictionary<string, Object>();
current = (Dictionary<string, Object>)current[part];
}
}
@ -250,6 +309,24 @@ namespace OpenSim.Framework.Console
info.fn = new List<CommandDelegate>();
info.fn.Add(fn);
current[String.Empty] = info;
// Now add command to modules dictionary
lock (m_modulesCommands)
{
List<CommandInfo> commands;
if (m_modulesCommands.ContainsKey(module))
{
commands = m_modulesCommands[module];
}
else
{
commands = new List<CommandInfo>();
m_modulesCommands[module] = commands;
}
// m_log.DebugFormat("[COMMAND CONSOLE]: Adding to category {0} command {1}", module, command);
commands.Add(info);
}
}
public string[] FindNextOption(string[] cmd, bool term)
@ -607,8 +684,9 @@ namespace OpenSim.Framework.Console
{
Commands = new Commands();
Commands.AddCommand("console", false, "help", "help [<command>]",
"Get general command list or more detailed help on a specific command", Help);
Commands.AddCommand(
"Help", false, "help", "help [<item>]",
"Display help on a particular command or on a list of commands in a category", Help);
}
private void Help(string module, string[] cmd)

View File

@ -0,0 +1,112 @@
/*
* 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.Linq;
using System.Text;
namespace OpenSim.Framework.Console
{
/// <summary>
/// Used to generated a formatted table for the console.
/// </summary>
/// <remarks>
/// Currently subject to change. If you use this, be prepared to change your code when this class changes.
/// </remarks>
public class ConsoleDisplayList
{
/// <summary>
/// The default divider between key and value for a list item.
/// </summary>
public const string DefaultKeyValueDivider = " : ";
/// <summary>
/// The divider used between key and value for a list item.
/// </summary>
public string KeyValueDivider { get; set; }
/// <summary>
/// Table rows
/// </summary>
public List<KeyValuePair<string, string>> Rows { get; private set; }
/// <summary>
/// Number of spaces to indent the list.
/// </summary>
public int Indent { get; set; }
public ConsoleDisplayList()
{
Rows = new List<KeyValuePair<string, string>>();
KeyValueDivider = DefaultKeyValueDivider;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
AddToStringBuilder(sb);
return sb.ToString();
}
public void AddToStringBuilder(StringBuilder sb)
{
string formatString = GetFormatString();
// System.Console.WriteLine("FORMAT STRING [{0}]", formatString);
// rows
foreach (KeyValuePair<string, string> row in Rows)
sb.AppendFormat(formatString, row.Key, row.Value);
}
/// <summary>
/// Gets the format string for the table.
/// </summary>
private string GetFormatString()
{
StringBuilder formatSb = new StringBuilder();
int longestKey = -1;
foreach (KeyValuePair<string, string> row in Rows)
if (row.Key.Length > longestKey)
longestKey = row.Key.Length;
formatSb.Append(' ', Indent);
// Can only do left formatting for now
formatSb.AppendFormat("{{0,-{0}}}{1}{{1}}\n", longestKey, KeyValueDivider);
return formatSb.ToString();
}
public void AddRow(object key, object value)
{
Rows.Add(new KeyValuePair<string, string>(key.ToString(), value.ToString()));
}
}
}

View File

@ -0,0 +1,154 @@
/*
* 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.Linq;
using System.Text;
namespace OpenSim.Framework.Console
{
/// <summary>
/// Used to generated a formatted table for the console.
/// </summary>
/// <remarks>
/// Currently subject to change. If you use this, be prepared to change your code when this class changes.
/// </remarks>
public class ConsoleDisplayTable
{
/// <summary>
/// Default number of spaces between table columns.
/// </summary>
public const int DefaultTableSpacing = 2;
/// <summary>
/// Table columns.
/// </summary>
public List<ConsoleDisplayTableColumn> Columns { get; private set; }
/// <summary>
/// Table rows
/// </summary>
public List<ConsoleDisplayTableRow> Rows { get; private set; }
/// <summary>
/// Number of spaces to indent the table.
/// </summary>
public int Indent { get; set; }
/// <summary>
/// Spacing between table columns
/// </summary>
public int TableSpacing { get; set; }
public ConsoleDisplayTable()
{
TableSpacing = DefaultTableSpacing;
Columns = new List<ConsoleDisplayTableColumn>();
Rows = new List<ConsoleDisplayTableRow>();
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
AddToStringBuilder(sb);
return sb.ToString();
}
public void AddColumn(string name, int width)
{
Columns.Add(new ConsoleDisplayTableColumn(name, width));
}
public void AddRow(params string[] cells)
{
Rows.Add(new ConsoleDisplayTableRow(cells));
}
public void AddToStringBuilder(StringBuilder sb)
{
string formatString = GetFormatString();
// System.Console.WriteLine("FORMAT STRING [{0}]", formatString);
// columns
sb.AppendFormat(formatString, Columns.ConvertAll(c => c.Header).ToArray());
// rows
foreach (ConsoleDisplayTableRow row in Rows)
sb.AppendFormat(formatString, row.Cells.ToArray());
}
/// <summary>
/// Gets the format string for the table.
/// </summary>
private string GetFormatString()
{
StringBuilder formatSb = new StringBuilder();
formatSb.Append(' ', Indent);
for (int i = 0; i < Columns.Count; i++)
{
formatSb.Append(' ', TableSpacing);
// Can only do left formatting for now
formatSb.AppendFormat("{{{0},-{1}}}", i, Columns[i].Width);
}
formatSb.Append('\n');
return formatSb.ToString();
}
}
public struct ConsoleDisplayTableColumn
{
public string Header { get; set; }
public int Width { get; set; }
public ConsoleDisplayTableColumn(string header, int width) : this()
{
Header = header;
Width = width;
}
}
public struct ConsoleDisplayTableRow
{
public List<string> Cells { get; private set; }
public ConsoleDisplayTableRow(List<string> cells) : this()
{
Cells = cells;
}
public ConsoleDisplayTableRow(params string[] cells) : this()
{
Cells = new List<string>(cells);
}
}
}

View File

@ -29,6 +29,7 @@ using System;
using System.Threading;
using System.Collections.Generic;
using System.Text;
using System.Xml;
namespace OpenSim.Framework.Console
{
@ -37,28 +38,42 @@ namespace OpenSim.Framework.Console
/// Don't use this except for Unit Testing or you're in for a world of hurt when the
/// sim gets to ReadLine
/// </summary>
public class MockConsole : CommandConsole
public class MockConsole : ICommandConsole
{
public MockConsole(string defaultPrompt) : base(defaultPrompt)
{
}
public override void Output(string text)
{
}
public override void Output(string text, string level)
{
}
private MockCommands m_commands = new MockCommands();
public override string ReadLine(string p, bool isCommand, bool e)
{
//Thread.CurrentThread.Join(1000);
return string.Empty;
}
public override void UnlockOutput()
{
}
public override void LockOutput()
{
}
public ICommands Commands { get { return m_commands; } }
public void Prompt() {}
public void RunCommand(string cmd) {}
public string ReadLine(string p, bool isCommand, bool e) { return ""; }
public object ConsoleScene { get { return null; } }
public void Output(string text, string level) {}
public void Output(string text) {}
public void OutputFormat(string format, params object[] components) {}
public string CmdPrompt(string p) { return ""; }
public string CmdPrompt(string p, string def) { return ""; }
public string CmdPrompt(string p, List<char> excludedCharacters) { return ""; }
public string CmdPrompt(string p, string def, List<char> excludedCharacters) { return ""; }
public string CmdPrompt(string prompt, string defaultresponse, List<string> options) { return ""; }
public string PasswdPrompt(string p) { return ""; }
}
public class MockCommands : ICommands
{
public void FromXml(XmlElement root, CommandDelegate fn) {}
public List<string> GetHelp(string[] cmd) { return null; }
public void AddCommand(string module, bool shared, string command, string help, string longhelp, CommandDelegate fn) {}
public void AddCommand(string module, bool shared, string command, string help, string longhelp, string descriptivehelp, CommandDelegate fn) {}
public string[] FindNextOption(string[] cmd, bool term) { return null; }
public string[] Resolve(string[] cmd) { return null; }
public XmlElement GetXml(XmlDocument doc) { return null; }
}
}

View File

@ -0,0 +1,62 @@
/*
* 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.Reflection;
using log4net;
public class GcNotify
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public static bool Enabled
{
get { return s_initialized; }
set
{
if (!s_initialized && value)
new GcNotify();
s_initialized = value;
}
}
private static bool s_initialized = false;
private GcNotify() {}
~GcNotify()
{
if (!Environment.HasShutdownStarted && !AppDomain.CurrentDomain.IsFinalizingForUnload())
{
m_log.DebugFormat("[GC NOTIFY]: Garbage collection triggered.");
if (Enabled)
new GcNotify();
}
}
}

View File

@ -296,9 +296,9 @@ namespace OpenSim.Framework
public delegate void ConfirmXfer(IClientAPI remoteClient, ulong xferID, uint packetID);
public delegate void FriendActionDelegate(
IClientAPI remoteClient, UUID agentID, UUID transactionID, List<UUID> callingCardFolders);
IClientAPI remoteClient, UUID transactionID, List<UUID> callingCardFolders);
public delegate void FriendshipTermination(IClientAPI remoteClient, UUID agentID, UUID ExID);
public delegate void FriendshipTermination(IClientAPI remoteClient, UUID ExID);
public delegate void MoneyTransferRequest(
UUID sourceID, UUID destID, int amount, int transactionType, string description);
@ -458,7 +458,7 @@ namespace OpenSim.Framework
public delegate void AvatarNotesUpdate(IClientAPI client, UUID targetID, string notes);
public delegate void MuteListRequest(IClientAPI client, uint muteCRC);
public delegate void AvatarInterestUpdate(IClientAPI client, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages);
public delegate void GrantUserFriendRights(IClientAPI client, UUID requester, UUID target, int rights);
public delegate void GrantUserFriendRights(IClientAPI client, UUID target, int rights);
public delegate void PlacesQuery(UUID QueryID, UUID TransactionID, string QueryText, uint QueryFlags, byte Category, string SimName, IClientAPI client);
public delegate void AgentFOV(IClientAPI client, float verticalAngle);
@ -710,7 +710,7 @@ namespace OpenSim.Framework
/// The scene agent for this client. This will only be set if the client has an agent in a scene (i.e. if it
/// is connected).
/// </summary>
ISceneAgent SceneAgent { get; }
ISceneAgent SceneAgent { get; set; }
UUID SessionId { get; }
@ -740,14 +740,21 @@ namespace OpenSim.Framework
/// </summary>
string Name { get; }
/// <value>
/// Determines whether the client thread is doing anything or not.
/// </value>
/// <summary>
/// True if the client is active (sending and receiving new UDP messages). False if the client is being closed.
/// </summary>
bool IsActive { get; set; }
/// <value>
/// Determines whether the client is or has been removed from a given scene
/// </value>
/// <summary>
/// Set if the client is closing due to a logout request
/// </summary>
/// <remarks>
/// Do not use this flag if you want to know if the client is closing, since it will not be set in other
/// circumstances (e.g. if a child agent is closed or the agent is kicked off the simulator). Use IsActive
/// instead with a IClientAPI.SceneAgent.IsChildAgent check if necessary.
///
/// Only set for root agents.
/// </remarks>
bool IsLoggingOut { get; set; }
bool SendLogoutPacketWhenClosing { set; }
@ -1026,7 +1033,21 @@ namespace OpenSim.Framework
void InPacket(object NewPack);
void ProcessInPacket(Packet NewPack);
/// <summary>
/// Close this client
/// </summary>
void Close();
/// <summary>
/// Close this client
/// </summary>
/// <param name='force'>
/// If true, attempts the close without checking active status. You do not want to try this except as a last
/// ditch attempt where Active == false but the ScenePresence still exists.
/// </param>
void Close(bool force);
void Kick(string message);
/// <summary>
@ -1347,7 +1368,6 @@ namespace OpenSim.Framework
void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message);
void SendLogoutPacket();
EndPoint GetClientEP();
// WARNING WARNING WARNING
//
@ -1408,8 +1428,6 @@ namespace OpenSim.Framework
void SendGroupVoteHistory(UUID groupID, UUID transactionID, GroupVoteHistory[] Votes);
void KillEndDone();
bool AddGenericPacketHandler(string MethodName, GenericMessage handler);
void SendRebakeAvatarTextures(UUID textureID);

View File

@ -40,7 +40,7 @@ namespace OpenSim.Framework
/// <summary>
/// Get help for the given help string
/// </summary>
/// <param name="helpParts">Parsed parts of the help string. If empty then general help is returned.</param>
/// <param name="cmd">Parsed parts of the help string. If empty then general help is returned.</param>
/// <returns></returns>
List<string> GetHelp(string[] cmd);

View File

@ -71,6 +71,7 @@ namespace OpenSim.Framework
bool IsEitherBannedOrRestricted(UUID avatar);
bool IsBannedFromLand(UUID avatar);
bool IsRestrictedFromLand(UUID avatar);
bool IsInLandAccessList(UUID avatar);
void SendLandUpdateToClient(IClientAPI remote_client);
void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client);
List<LandAccessEntry> CreateAccessListArrayByFlag(AccessList flag);

View File

@ -56,11 +56,29 @@ namespace OpenSim.Framework
public interface IScene
{
/// <summary>
/// The name of this scene.
/// </summary>
string Name { get; }
RegionInfo RegionInfo { get; }
RegionStatus RegionStatus { get; set; }
IConfigSource Config { get; }
/// <summary>
/// Are logins enabled on this simulator?
/// </summary>
bool LoginsEnabled { get; set; }
/// <summary>
/// Is this region ready for use?
/// </summary>
/// <remarks>
/// This does not mean that logins are enabled, merely that they can be.
/// </remarks>
bool Ready { get; set; }
float TimeDilation { get; }
bool AllowScriptCrossings { get; }

View File

@ -26,6 +26,7 @@
*/
using System;
using OpenMetaverse;
namespace OpenSim.Framework
{
@ -71,5 +72,11 @@ namespace OpenSim.Framework
/// This includes scene object data and the appearance data of other avatars.
/// </remarks>
void SendInitialDataToMe();
/// <summary>
/// Direction in which the scene presence is looking.
/// </summary>
/// <remarks>Will be Vector3.Zero for a child agent.</remarks>
Vector3 Lookat { get; }
}
}

View File

@ -69,7 +69,7 @@ namespace OpenSim.Framework
(uint) ParcelFlags.AllowAPrimitiveEntry |
(uint) ParcelFlags.AllowDeedToGroup | (uint) ParcelFlags.AllowTerraform |
(uint) ParcelFlags.CreateObjects | (uint) ParcelFlags.AllowOtherScripts |
(uint) ParcelFlags.SoundLocal;
(uint) ParcelFlags.SoundLocal | (uint) ParcelFlags.AllowVoiceChat;
private byte _landingType = 0;
private string _name = "Your Parcel";

View File

@ -101,6 +101,11 @@ namespace OpenSim.Framework
{
item = oldHeadNext.Item;
haveAdvancedHead = CAS(ref head, oldHead, oldHeadNext);
if (haveAdvancedHead)
{
oldHeadNext.Item = default(T);
oldHead.Next = null;
}
}
}
}
@ -111,6 +116,10 @@ namespace OpenSim.Framework
public void Clear()
{
// ugly
T item;
while(count > 0)
Dequeue(out item);
Init();
}

View File

@ -0,0 +1,129 @@
/*
* 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.Linq;
using System.Reflection;
using System.Threading;
using log4net;
namespace OpenSim.Framework
{
/// <summary>
/// Experimental watchdog for memory usage.
/// </summary>
public static class MemoryWatchdog
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// Is this watchdog active?
/// </summary>
public static bool Enabled
{
get { return m_enabled; }
set
{
// m_log.DebugFormat("[MEMORY WATCHDOG]: Setting MemoryWatchdog.Enabled to {0}", value);
if (value && !m_enabled)
UpdateLastRecord(GC.GetTotalMemory(false), Util.EnvironmentTickCount());
m_enabled = value;
}
}
private static bool m_enabled;
/// <summary>
/// Average memory churn in bytes per millisecond.
/// </summary>
public static double AverageMemoryChurn
{
get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; }
}
/// <summary>
/// Maximum number of statistical samples.
/// </summary>
/// <remarks>
/// At the moment this corresponds to 1 minute since the sampling rate is every 2.5 seconds as triggered from
/// the main Watchdog.
/// </remarks>
private static int m_maxSamples = 24;
/// <summary>
/// Time when the watchdog was last updated.
/// </summary>
private static int m_lastUpdateTick;
/// <summary>
/// Memory used at time of last watchdog update.
/// </summary>
private static long m_lastUpdateMemory;
/// <summary>
/// Memory churn rate per millisecond.
/// </summary>
private static double m_churnRatePerMillisecond;
/// <summary>
/// Historical samples for calculating moving average.
/// </summary>
private static Queue<double> m_samples = new Queue<double>(m_maxSamples);
public static void Update()
{
int now = Util.EnvironmentTickCount();
long memoryNow = GC.GetTotalMemory(false);
long memoryDiff = memoryNow - m_lastUpdateMemory;
if (memoryDiff >= 0)
{
if (m_samples.Count >= m_maxSamples)
m_samples.Dequeue();
double elapsed = Util.EnvironmentTickCountSubtract(now, m_lastUpdateTick);
// This should never happen since it's not useful for updates to occur with no time elapsed, but
// protect ourselves from a divide-by-zero just in case.
if (elapsed == 0)
return;
m_samples.Enqueue(memoryDiff / (double)elapsed);
}
UpdateLastRecord(memoryNow, now);
}
private static void UpdateLastRecord(long memoryNow, int timeNow)
{
m_lastUpdateMemory = memoryNow;
m_lastUpdateTick = timeNow;
}
}
}

View File

@ -63,12 +63,15 @@ namespace OpenSim.Framework
internal void Clear()
{
this.value = default(T);
if (this.handle != null)
{
this.handle.Clear();
this.handle = null;
}
ClearRef();
}
internal void ClearRef()
{
this.value = default(T);
this.handle = null;
}
}
@ -285,6 +288,7 @@ namespace OpenSim.Framework
if (--this.size > 0 && index != this.size)
{
Set(this.items[this.size], index);
this.items[this.size].ClearRef();
if (!BubbleUp(index))
BubbleDown(index);
}

View File

@ -44,8 +44,6 @@ namespace OpenSim.Framework.Serialization.External
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected static UTF8Encoding m_utf8Encoding = new UTF8Encoding();
private static Dictionary<string, Action<LandData, XmlTextReader>> m_ldProcessors
= new Dictionary<string, Action<LandData, XmlTextReader>>();
@ -163,7 +161,7 @@ namespace OpenSim.Framework.Serialization.External
/// <exception cref="System.Xml.XmlException"></exception>
public static LandData Deserialize(byte[] serializedLandData)
{
return Deserialize(m_utf8Encoding.GetString(serializedLandData, 0, serializedLandData.Length));
return Deserialize(Encoding.UTF8.GetString(serializedLandData, 0, serializedLandData.Length));
}
/// <summary>

View File

@ -38,8 +38,6 @@ namespace OpenSim.Framework.Serialization.External
/// </summary>
public class RegionSettingsSerializer
{
protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
/// <summary>
/// Deserialize settings
/// </summary>
@ -48,7 +46,7 @@ namespace OpenSim.Framework.Serialization.External
/// <exception cref="System.Xml.XmlException"></exception>
public static RegionSettings Deserialize(byte[] serializedSettings)
{
return Deserialize(m_asciiEncoding.GetString(serializedSettings, 0, serializedSettings.Length));
return Deserialize(Encoding.ASCII.GetString(serializedSettings, 0, serializedSettings.Length));
}
/// <summary>

View File

@ -53,8 +53,6 @@ namespace OpenSim.Framework.Serialization
TYPE_CONTIGUOUS_FILE = 8,
}
protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
/// <summary>
/// Binary reader for the underlying stream
/// </summary>
@ -120,13 +118,13 @@ namespace OpenSim.Framework.Serialization
if (header[156] == (byte)'L')
{
int longNameLength = ConvertOctalBytesToDecimal(header, 124, 11);
tarHeader.FilePath = m_asciiEncoding.GetString(ReadData(longNameLength));
tarHeader.FilePath = Encoding.ASCII.GetString(ReadData(longNameLength));
//m_log.DebugFormat("[TAR ARCHIVE READER]: Got long file name {0}", tarHeader.FilePath);
header = m_br.ReadBytes(512);
}
else
{
tarHeader.FilePath = m_asciiEncoding.GetString(header, 0, 100);
tarHeader.FilePath = Encoding.ASCII.GetString(header, 0, 100);
tarHeader.FilePath = tarHeader.FilePath.Trim(m_nullCharArray);
//m_log.DebugFormat("[TAR ARCHIVE READER]: Got short file name {0}", tarHeader.FilePath);
}
@ -205,7 +203,7 @@ namespace OpenSim.Framework.Serialization
{
// Trim leading white space: ancient tars do that instead
// of leading 0s :-( don't ask. really.
string oString = m_asciiEncoding.GetString(bytes, startIndex, count).TrimStart(m_spaceCharArray);
string oString = Encoding.ASCII.GetString(bytes, startIndex, count).TrimStart(m_spaceCharArray);
int d = 0;

View File

@ -41,9 +41,6 @@ namespace OpenSim.Framework.Serialization
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
protected static UTF8Encoding m_utf8Encoding = new UTF8Encoding();
/// <summary>
/// Binary writer for the underlying stream
/// </summary>
@ -74,7 +71,7 @@ namespace OpenSim.Framework.Serialization
/// <param name="data"></param>
public void WriteFile(string filePath, string data)
{
WriteFile(filePath, m_utf8Encoding.GetBytes(data));
WriteFile(filePath, Util.UTF8NoBomEncoding.GetBytes(data));
}
/// <summary>
@ -85,7 +82,7 @@ namespace OpenSim.Framework.Serialization
public void WriteFile(string filePath, byte[] data)
{
if (filePath.Length > 100)
WriteEntry("././@LongLink", m_asciiEncoding.GetBytes(filePath), 'L');
WriteEntry("././@LongLink", Encoding.ASCII.GetBytes(filePath), 'L');
char fileType;
@ -137,7 +134,7 @@ namespace OpenSim.Framework.Serialization
oString = "0" + oString;
}
byte[] oBytes = m_asciiEncoding.GetBytes(oString);
byte[] oBytes = Encoding.ASCII.GetBytes(oString);
return oBytes;
}
@ -156,20 +153,20 @@ namespace OpenSim.Framework.Serialization
byte[] header = new byte[512];
// file path field (100)
byte[] nameBytes = m_asciiEncoding.GetBytes(filePath);
byte[] nameBytes = Encoding.ASCII.GetBytes(filePath);
int nameSize = (nameBytes.Length >= 100) ? 100 : nameBytes.Length;
Array.Copy(nameBytes, header, nameSize);
// file mode (8)
byte[] modeBytes = m_asciiEncoding.GetBytes("0000777");
byte[] modeBytes = Encoding.ASCII.GetBytes("0000777");
Array.Copy(modeBytes, 0, header, 100, 7);
// owner user id (8)
byte[] ownerIdBytes = m_asciiEncoding.GetBytes("0000764");
byte[] ownerIdBytes = Encoding.ASCII.GetBytes("0000764");
Array.Copy(ownerIdBytes, 0, header, 108, 7);
// group user id (8)
byte[] groupIdBytes = m_asciiEncoding.GetBytes("0000764");
byte[] groupIdBytes = Encoding.ASCII.GetBytes("0000764");
Array.Copy(groupIdBytes, 0, header, 116, 7);
// file size in bytes (12)
@ -181,17 +178,17 @@ namespace OpenSim.Framework.Serialization
Array.Copy(fileSizeBytes, 0, header, 124, 11);
// last modification time (12)
byte[] lastModTimeBytes = m_asciiEncoding.GetBytes("11017037332");
byte[] lastModTimeBytes = Encoding.ASCII.GetBytes("11017037332");
Array.Copy(lastModTimeBytes, 0, header, 136, 11);
// entry type indicator (1)
header[156] = m_asciiEncoding.GetBytes(new char[] { fileType })[0];
header[156] = Encoding.ASCII.GetBytes(new char[] { fileType })[0];
Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 329, 7);
Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 337, 7);
Array.Copy(Encoding.ASCII.GetBytes("0000000"), 0, header, 329, 7);
Array.Copy(Encoding.ASCII.GetBytes("0000000"), 0, header, 337, 7);
// check sum for header block (8) [calculated last]
Array.Copy(m_asciiEncoding.GetBytes(" "), 0, header, 148, 8);
Array.Copy(Encoding.ASCII.GetBytes(" "), 0, header, 148, 8);
int checksum = 0;
foreach (byte b in header)

View File

@ -161,43 +161,43 @@ namespace OpenSim.Framework.Servers
Notice(String.Format("Console log level is {0}", m_consoleAppender.Threshold));
}
m_console.Commands.AddCommand("base", false, "quit",
m_console.Commands.AddCommand("General", false, "quit",
"quit",
"Quit the application", HandleQuit);
m_console.Commands.AddCommand("base", false, "shutdown",
m_console.Commands.AddCommand("General", false, "shutdown",
"shutdown",
"Quit the application", HandleQuit);
m_console.Commands.AddCommand("base", false, "set log level",
m_console.Commands.AddCommand("General", false, "set log level",
"set log level <level>",
"Set the console logging level", HandleLogLevel);
m_console.Commands.AddCommand("base", false, "show info",
m_console.Commands.AddCommand("General", false, "show info",
"show info",
"Show general information about the server", HandleShow);
m_console.Commands.AddCommand("base", false, "show stats",
m_console.Commands.AddCommand("General", false, "show stats",
"show stats",
"Show statistics", HandleShow);
m_console.Commands.AddCommand("base", false, "show threads",
m_console.Commands.AddCommand("General", false, "show threads",
"show threads",
"Show thread status", HandleShow);
m_console.Commands.AddCommand("base", false, "show uptime",
m_console.Commands.AddCommand("General", false, "show uptime",
"show uptime",
"Show server uptime", HandleShow);
m_console.Commands.AddCommand("base", false, "show version",
m_console.Commands.AddCommand("General", false, "show version",
"show version",
"Show server version", HandleShow);
m_console.Commands.AddCommand("base", false, "threads abort",
m_console.Commands.AddCommand("General", false, "threads abort",
"threads abort <thread-id>",
"Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
m_console.Commands.AddCommand("base", false, "threads show",
m_console.Commands.AddCommand("General", false, "threads show",
"threads show",
"Show thread status. Synonym for \"show threads\"",
(string module, string[] args) => Notice(GetThreadsReport()));
@ -269,15 +269,19 @@ namespace OpenSim.Framework.Servers
t.Priority,
t.ThreadState);
sb.Append(Environment.NewLine);
sb.Append("\n");
}
int workers = 0, ports = 0, maxWorkers = 0, maxPorts = 0;
ThreadPool.GetAvailableThreads(out workers, out ports);
ThreadPool.GetMaxThreads(out maxWorkers, out maxPorts);
sb.Append("\n");
sb.Append(Environment.NewLine + "*** ThreadPool threads ***" + Environment.NewLine);
sb.Append("workers: " + (maxWorkers - workers) + " (" + maxWorkers + "); ports: " + (maxPorts - ports) + " (" + maxPorts + ")" + Environment.NewLine);
// For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting
// zero active threads.
int totalThreads = Process.GetCurrentProcess().Threads.Count;
if (totalThreads > 0)
sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
sb.Append("Main threadpool (excluding script engine pools)\n");
sb.Append(Util.GetThreadPoolReport());
return sb.ToString();
}
@ -316,7 +320,9 @@ namespace OpenSim.Framework.Servers
TimeSpan timeTaken = DateTime.Now - m_startuptime;
m_log.InfoFormat("[STARTUP]: Startup took {0}m {1}s", timeTaken.Minutes, timeTaken.Seconds);
m_log.InfoFormat(
"[STARTUP]: Non-script portion of startup took {0}m {1}s. PLEASE WAIT FOR LOGINS TO BE ENABLED ON REGIONS ONCE SCRIPTS HAVE STARTED.",
timeTaken.Minutes, timeTaken.Seconds);
}
/// <summary>
@ -585,8 +591,8 @@ namespace OpenSim.Framework.Servers
{
string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
FileStream fs = File.Create(path);
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
Byte[] buf = enc.GetBytes(pidstring);
Byte[] buf = Encoding.ASCII.GetBytes(pidstring);
fs.Write(buf, 0, buf.Length);
fs.Close();
m_pidFile = path;

View File

@ -33,9 +33,9 @@ namespace OpenSim.Framework.Servers.HttpServer
{
public abstract Hashtable Handle(string path, Hashtable Request);
protected BaseHTTPHandler(string httpMethod, string path)
: base(httpMethod, path)
{
}
protected BaseHTTPHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
protected BaseHTTPHandler(string httpMethod, string path, string name, string description)
: base(httpMethod, path, name, description) {}
}
}

View File

@ -53,6 +53,8 @@ namespace OpenSim.Framework.Servers.HttpServer
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
public int DebugLevel { get; set; }
private volatile int NotSocketErrors = 0;
public volatile bool HTTPDRunning = false;
@ -79,11 +81,6 @@ namespace OpenSim.Framework.Servers.HttpServer
private PollServiceRequestManager m_PollServiceManager;
/// <summary>
/// Control the printing of certain debug messages.
/// </summary>
public int DebugLevel { get; set; }
public uint SSLPort
{
get { return m_sslport; }
@ -156,7 +153,7 @@ namespace OpenSim.Framework.Servers.HttpServer
}
}
public List<string> GetStreamHandlerKeys()
public List<string> GetStreamHandlerKeys()
{
lock (m_streamHandlers)
return new List<string>(m_streamHandlers.Keys);
@ -356,7 +353,7 @@ namespace OpenSim.Framework.Servers.HttpServer
}
catch (Exception e)
{
m_log.ErrorFormat("[BASE HTTP SERVER]: OnRequest() failed with {0}{1}", e.Message, e.StackTrace);
m_log.Error(String.Format("[BASE HTTP SERVER]: OnRequest() failed: {0} ", e.Message), e);
}
}
@ -408,7 +405,12 @@ namespace OpenSim.Framework.Servers.HttpServer
string uriString = request.RawUrl;
// string reqnum = "unknown";
int tickstart = Environment.TickCount;
int requestStartTick = Environment.TickCount;
// Will be adjusted later on.
int requestEndTick = requestStartTick;
IRequestHandler requestHandler = null;
try
{
@ -431,6 +433,7 @@ namespace OpenSim.Framework.Servers.HttpServer
{
if (HandleAgentRequest(agentHandler, request, response))
{
requestEndTick = Environment.TickCount;
return;
}
}
@ -438,20 +441,14 @@ namespace OpenSim.Framework.Servers.HttpServer
//response.KeepAlive = true;
response.SendChunked = false;
IRequestHandler requestHandler;
string path = request.RawUrl;
string handlerKey = GetHandlerKey(request.HttpMethod, path);
byte[] buffer = null;
if (TryGetStreamHandler(handlerKey, out requestHandler))
{
if (DebugLevel >= 1)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found stream handler for {0} {1}",
request.HttpMethod, request.Url.PathAndQuery);
// Okay, so this is bad, but should be considered temporary until everything is IStreamHandler.
byte[] buffer = null;
if (DebugLevel >= 3)
LogIncomingToStreamHandler(request, requestHandler);
response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type.
@ -507,8 +504,8 @@ namespace OpenSim.Framework.Servers.HttpServer
//m_log.Warn("[HTTP]: " + requestBody);
}
DoHTTPGruntWork(HTTPRequestHandler.Handle(path, keysvals), response);
return;
buffer = DoHTTPGruntWork(HTTPRequestHandler.Handle(path, keysvals), response);
}
else
{
@ -521,133 +518,93 @@ namespace OpenSim.Framework.Servers.HttpServer
buffer = memoryStream.ToArray();
}
}
}
else
{
switch (request.ContentType)
{
case null:
case "text/html":
request.InputStream.Close();
if (DebugLevel >= 3)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
// HTTP IN support. The script engine takes it from here
// Nothing to worry about for us.
//
if (buffer == null)
return;
buffer = HandleHTTPRequest(request, response);
break;
case "application/llsd+xml":
case "application/xml+llsd":
case "application/llsd+json":
if (DebugLevel >= 3)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
buffer = HandleLLSDRequests(request, response);
break;
case "text/xml":
case "application/xml":
case "application/json":
default:
//m_log.Info("[Debug BASE HTTP SERVER]: in default handler");
// Point of note.. the DoWeHaveA methods check for an EXACT path
// if (request.RawUrl.Contains("/CAPS/EQG"))
// {
// int i = 1;
// }
//m_log.Info("[Debug BASE HTTP SERVER]: Checking for LLSD Handler");
if (DoWeHaveALLSDHandler(request.RawUrl))
{
if (DebugLevel >= 3)
LogIncomingToContentTypeHandler(request);
buffer = HandleLLSDRequests(request, response);
}
// m_log.DebugFormat("[BASE HTTP SERVER]: Checking for HTTP Handler for request {0}", request.RawUrl);
else if (DoWeHaveAHTTPHandler(request.RawUrl))
{
if (DebugLevel >= 3)
LogIncomingToContentTypeHandler(request);
buffer = HandleHTTPRequest(request, response);
}
else
{
if (DebugLevel >= 3)
LogIncomingToXmlRpcHandler(request);
// generic login request.
buffer = HandleXmlRpcRequests(request, response);
}
break;
}
}
request.InputStream.Close();
if (buffer != null)
{
if (!response.SendChunked)
response.ContentLength64 = buffer.LongLength;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
//response.OutputStream.Close();
}
catch (HttpListenerException)
{
m_log.WarnFormat("[BASE HTTP SERVER]: HTTP request abnormally terminated.");
}
//response.OutputStream.Close();
try
{
response.Send();
//response.FreeContext();
}
catch (SocketException e)
{
// This has to be here to prevent a Linux/Mono crash
m_log.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
}
catch (IOException e)
{
m_log.Warn("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e.Message);
}
return;
response.OutputStream.Write(buffer, 0, buffer.Length);
}
if (request.AcceptTypes != null && request.AcceptTypes.Length > 0)
{
foreach (string strAccept in request.AcceptTypes)
{
if (strAccept.Contains("application/llsd+xml") ||
strAccept.Contains("application/llsd+json"))
{
if (DebugLevel >= 1)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found application/llsd+xml accept header handler for {0} {1}",
request.HttpMethod, request.Url.PathAndQuery);
// Do not include the time taken to actually send the response to the caller in the measurement
// time. This is to avoid logging when it's the client that is slow to process rather than the
// server
requestEndTick = Environment.TickCount;
HandleLLSDRequests(request, response);
return;
}
}
}
response.Send();
switch (request.ContentType)
{
case null:
case "text/html":
//response.OutputStream.Close();
if (DebugLevel >= 1)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
HandleHTTPRequest(request, response);
return;
case "application/llsd+xml":
case "application/xml+llsd":
case "application/llsd+json":
if (DebugLevel >= 1)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
HandleLLSDRequests(request, response);
return;
case "text/xml":
case "application/xml":
case "application/json":
default:
//m_log.Info("[Debug BASE HTTP SERVER]: in default handler");
// Point of note.. the DoWeHaveA methods check for an EXACT path
// if (request.RawUrl.Contains("/CAPS/EQG"))
// {
// int i = 1;
// }
//m_log.Info("[Debug BASE HTTP SERVER]: Checking for LLSD Handler");
if (DoWeHaveALLSDHandler(request.RawUrl))
{
if (DebugLevel >= 1)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
HandleLLSDRequests(request, response);
return;
}
// m_log.DebugFormat("[BASE HTTP SERVER]: Checking for HTTP Handler for request {0}", request.RawUrl);
if (DoWeHaveAHTTPHandler(request.RawUrl))
{
if (DebugLevel >= 1)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
HandleHTTPRequest(request, response);
return;
}
if (DebugLevel >= 1)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}",
request.HttpMethod, request.Url.PathAndQuery);
// generic login request.
HandleXmlRpcRequests(request, response);
return;
}
//response.FreeContext();
}
catch (SocketException e)
{
@ -658,25 +615,85 @@ namespace OpenSim.Framework.Servers.HttpServer
//
// An alternative may be to turn off all response write exceptions on the HttpListener, but let's go
// with the minimum first
m_log.WarnFormat("[BASE HTTP SERVER]: HandleRequest threw {0}.\nNOTE: this may be spurious on Linux", e);
m_log.Warn(String.Format("[BASE HTTP SERVER]: HandleRequest threw {0}.\nNOTE: this may be spurious on Linux ", e.Message), e);
}
catch (IOException e)
{
m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw ", e);
m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.Message), e);
}
catch (Exception e)
{
m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw " + e.ToString());
m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.Message), e);
SendHTML500(response);
}
finally
{
// Every month or so this will wrap and give bad numbers, not really a problem
// since its just for reporting, tickdiff limit can be adjusted
int tickdiff = Environment.TickCount - tickstart;
// since its just for reporting
int tickdiff = requestEndTick - requestStartTick;
if (tickdiff > 3000)
{
m_log.InfoFormat(
"[BASE HTTP SERVER]: slow {0} request for {1} from {2} took {3} ms", requestMethod, uriString, request.RemoteIPEndPoint.ToString(), tickdiff);
"[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} from {4} took {5}ms",
requestMethod,
uriString,
requestHandler != null ? requestHandler.Name : "",
requestHandler != null ? requestHandler.Description : "",
request.RemoteIPEndPoint.ToString(),
tickdiff);
}
}
}
private void LogIncomingToStreamHandler(OSHttpRequest request, IRequestHandler requestHandler)
{
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found stream handler for {0} {1} {2} {3}",
request.HttpMethod, request.Url.PathAndQuery, requestHandler.Name, requestHandler.Description);
if (DebugLevel >= 4)
LogIncomingInDetail(request);
}
private void LogIncomingToContentTypeHandler(OSHttpRequest request)
{
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
if (DebugLevel >= 4)
LogIncomingInDetail(request);
}
private void LogIncomingToXmlRpcHandler(OSHttpRequest request)
{
m_log.DebugFormat(
"[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}",
request.HttpMethod, request.Url.PathAndQuery);
if (DebugLevel >= 4)
LogIncomingInDetail(request);
}
private void LogIncomingInDetail(OSHttpRequest request)
{
using (StreamReader reader = new StreamReader(Util.Copy(request.InputStream), Encoding.UTF8))
{
string output;
if (DebugLevel == 4)
{
const int sampleLength = 80;
char[] sampleChars = new char[sampleLength];
reader.Read(sampleChars, 0, sampleLength);
output = string.Format("[BASE HTTP SERVER]: {0}...", new string(sampleChars).Replace("\n", @"\n"));
}
else
{
output = string.Format("[BASE HTTP SERVER]: {0}", reader.ReadToEnd());
}
m_log.Debug(output);
}
}
@ -797,7 +814,7 @@ namespace OpenSim.Framework.Servers.HttpServer
/// </summary>
/// <param name="request"></param>
/// <param name="response"></param>
private void HandleXmlRpcRequests(OSHttpRequest request, OSHttpResponse response)
private byte[] HandleXmlRpcRequests(OSHttpRequest request, OSHttpResponse response)
{
Stream requestStream = request.InputStream;
@ -816,8 +833,23 @@ namespace OpenSim.Framework.Servers.HttpServer
{
xmlRprcRequest = (XmlRpcRequest) (new XmlRpcRequestDeserializer()).Deserialize(requestBody);
}
catch (XmlException)
catch (XmlException e)
{
if (DebugLevel >= 1)
{
if (DebugLevel >= 2)
m_log.Warn(
string.Format(
"[BASE HTTP SERVER]: Got XMLRPC request with invalid XML from {0}. XML was '{1}'. Sending blank response. Exception ",
request.RemoteIPEndPoint, requestBody),
e);
else
{
m_log.WarnFormat(
"[BASE HTTP SERVER]: Got XMLRPC request with invalid XML from {0}, length {1}. Sending blank response.",
request.RemoteIPEndPoint, requestBody.Length);
}
}
}
if (xmlRprcRequest != null)
@ -887,6 +919,7 @@ namespace OpenSim.Framework.Servers.HttpServer
String.Format("Requested method [{0}] not found", methodName));
}
response.ContentType = "text/xml";
responseString = XmlRpcResponseSerializer.Singleton.Serialize(xmlRpcResponse);
}
else
@ -896,82 +929,25 @@ namespace OpenSim.Framework.Servers.HttpServer
response.StatusCode = 404;
response.StatusDescription = "Not Found";
response.ProtocolVersion = "HTTP/1.0";
byte[] buf = Encoding.UTF8.GetBytes("Not found");
responseString = "Not found";
response.KeepAlive = false;
m_log.ErrorFormat(
"[BASE HTTP SERVER]: Handler not found for http request {0} {1}",
request.HttpMethod, request.Url.PathAndQuery);
response.SendChunked = false;
response.ContentLength64 = buf.Length;
response.ContentEncoding = Encoding.UTF8;
try
{
response.OutputStream.Write(buf, 0, buf.Length);
}
catch (Exception ex)
{
m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
}
finally
{
try
{
response.Send();
//response.FreeContext();
}
catch (SocketException e)
{
// This has to be here to prevent a Linux/Mono crash
m_log.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
}
catch (IOException e)
{
m_log.Warn("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e.Message);
}
}
return;
//responseString = "Error";
}
}
response.ContentType = "text/xml";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
response.SendChunked = false;
response.ContentLength64 = buffer.Length;
response.ContentEncoding = Encoding.UTF8;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
}
finally
{
try
{
response.Send();
//response.FreeContext();
}
catch (SocketException e)
{
// This has to be here to prevent a Linux/Mono crash
m_log.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
}
catch (IOException e)
{
m_log.Warn("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e.Message);
}
}
return buffer;
}
private void HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response)
private byte[] HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response)
{
//m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request");
Stream requestStream = request.InputStream;
@ -1057,34 +1033,7 @@ namespace OpenSim.Framework.Servers.HttpServer
response.ContentEncoding = Encoding.UTF8;
response.KeepAlive = true;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
}
finally
{
//response.OutputStream.Close();
try
{
response.Send();
response.OutputStream.Flush();
//response.FreeContext();
//response.OutputStream.Close();
}
catch (IOException e)
{
m_log.WarnFormat("[BASE HTTP SERVER]: LLSD IOException {0}.", e);
}
catch (SocketException e)
{
// This has to be here to prevent a Linux/Mono crash
m_log.WarnFormat("[BASE HTTP SERVER]: LLSD issue {0}.\nNOTE: this may be spurious on Linux.", e);
}
}
return buffer;
}
private byte[] BuildLLSDResponse(OSHttpRequest request, OSHttpResponse response, OSD llsdResponse)
@ -1334,8 +1283,8 @@ namespace OpenSim.Framework.Servers.HttpServer
catch (SocketException f)
{
// This has to be here to prevent a Linux/Mono crash
m_log.WarnFormat(
"[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", f);
m_log.Warn(
String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", f.Message), f);
}
}
catch(Exception)
@ -1349,7 +1298,7 @@ namespace OpenSim.Framework.Servers.HttpServer
}
public void HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response)
public byte[] HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response)
{
// m_log.DebugFormat(
// "[BASE HTTP SERVER]: HandleHTTPRequest for request to {0}, method {1}",
@ -1359,15 +1308,14 @@ namespace OpenSim.Framework.Servers.HttpServer
{
case "OPTIONS":
response.StatusCode = (int)OSHttpStatusCode.SuccessOk;
return;
return null;
default:
HandleContentVerbs(request, response);
return;
return HandleContentVerbs(request, response);
}
}
private void HandleContentVerbs(OSHttpRequest request, OSHttpResponse response)
private byte[] HandleContentVerbs(OSHttpRequest request, OSHttpResponse response)
{
// m_log.DebugFormat("[BASE HTTP SERVER]: HandleContentVerbs for request to {0}", request.RawUrl);
@ -1383,6 +1331,8 @@ namespace OpenSim.Framework.Servers.HttpServer
// to display the form, or process it.
// a better way would be nifty.
byte[] buffer;
Stream requestStream = request.InputStream;
Encoding encoding = Encoding.UTF8;
@ -1443,14 +1393,14 @@ namespace OpenSim.Framework.Servers.HttpServer
if (foundHandler)
{
Hashtable responsedata1 = requestprocessor(keysvals);
DoHTTPGruntWork(responsedata1,response);
buffer = DoHTTPGruntWork(responsedata1,response);
//SendHTML500(response);
}
else
{
// m_log.Warn("[BASE HTTP SERVER]: Handler Not Found");
SendHTML404(response, host);
buffer = SendHTML404(response, host);
}
}
else
@ -1460,16 +1410,18 @@ namespace OpenSim.Framework.Servers.HttpServer
if (foundHandler)
{
Hashtable responsedata2 = requestprocessor(keysvals);
DoHTTPGruntWork(responsedata2, response);
buffer = DoHTTPGruntWork(responsedata2, response);
//SendHTML500(response);
}
else
{
// m_log.Warn("[BASE HTTP SERVER]: Handler Not Found2");
SendHTML404(response, host);
buffer = SendHTML404(response, host);
}
}
return buffer;
}
private bool TryGetHTTPHandlerPathBased(string path, out GenericHTTPMethod httpHandler)
@ -1537,14 +1489,13 @@ namespace OpenSim.Framework.Servers.HttpServer
}
}
internal void DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response)
internal byte[] DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response)
{
//m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response");
int responsecode = (int)responsedata["int_response_code"];
string responseString = (string)responsedata["str_response_string"];
string contentType = (string)responsedata["content_type"];
if (responsedata.ContainsKey("error_status_text"))
{
response.StatusDescription = (string)responsedata["error_status_text"];
@ -1608,38 +1559,10 @@ namespace OpenSim.Framework.Servers.HttpServer
response.ContentLength64 = buffer.Length;
response.ContentEncoding = Encoding.UTF8;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
m_log.Warn("[HTTPD]: Error - " + ex.Message);
}
finally
{
//response.OutputStream.Close();
try
{
response.OutputStream.Flush();
response.Send();
//if (!response.KeepAlive && response.ReuseContext)
// response.FreeContext();
}
catch (SocketException e)
{
// This has to be here to prevent a Linux/Mono crash
m_log.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
}
catch (IOException e)
{
m_log.Warn("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e.Message);
}
}
return buffer;
}
public void SendHTML404(OSHttpResponse response, string host)
public byte[] SendHTML404(OSHttpResponse response, string host)
{
// I know this statuscode is dumb, but the client doesn't respond to 404s and 500s
response.StatusCode = 404;
@ -1652,31 +1575,10 @@ namespace OpenSim.Framework.Servers.HttpServer
response.ContentLength64 = buffer.Length;
response.ContentEncoding = Encoding.UTF8;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
}
finally
{
//response.OutputStream.Close();
try
{
response.Send();
//response.FreeContext();
}
catch (SocketException e)
{
// This has to be here to prevent a Linux/Mono crash
m_log.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
}
}
return buffer;
}
public void SendHTML500(OSHttpResponse response)
public byte[] SendHTML500(OSHttpResponse response)
{
// I know this statuscode is dumb, but the client doesn't respond to 404s and 500s
response.StatusCode = (int)OSHttpStatusCode.SuccessOk;
@ -1688,28 +1590,8 @@ namespace OpenSim.Framework.Servers.HttpServer
response.SendChunked = false;
response.ContentLength64 = buffer.Length;
response.ContentEncoding = Encoding.UTF8;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
}
finally
{
//response.OutputStream.Close();
try
{
response.Send();
//response.FreeContext();
}
catch (SocketException e)
{
// This has to be here to prevent a Linux/Mono crash
m_log.WarnFormat("[BASE HTTP SERVER] XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
}
}
return buffer;
}
public void Start()
@ -1719,6 +1601,9 @@ namespace OpenSim.Framework.Servers.HttpServer
private void StartHTTP()
{
m_log.InfoFormat(
"[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port);
try
{
//m_httpListener = new HttpListener();
@ -1786,7 +1671,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public void httpServerException(object source, Exception exception)
{
m_log.ErrorFormat("[BASE HTTP SERVER]: {0} had an exception {1}", source.ToString(), exception.ToString());
m_log.Error(String.Format("[BASE HTTP SERVER]: {0} had an exception: {1} ", source.ToString(), exception.Message), exception);
/*
if (HTTPDRunning)// && NotSocketErrors > 5)
{

View File

@ -45,8 +45,16 @@ namespace OpenSim.Framework.Servers.HttpServer
private readonly string m_path;
protected BaseRequestHandler(string httpMethod, string path)
public string Name { get; private set; }
public string Description { get; private set; }
protected BaseRequestHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
protected BaseRequestHandler(string httpMethod, string path, string name, string description)
{
Name = name;
Description = description;
m_httpMethod = httpMethod;
m_path = path;
}

View File

@ -34,8 +34,9 @@ namespace OpenSim.Framework.Servers.HttpServer
public abstract byte[] Handle(string path, Stream request,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse);
protected BaseStreamHandler(string httpMethod, string path) : base(httpMethod, path)
{
}
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) {}
}
}

View File

@ -36,6 +36,15 @@ namespace OpenSim.Framework.Servers.HttpServer
{
private BinaryMethod m_method;
public BinaryStreamHandler(string httpMethod, string path, BinaryMethod binaryMethod)
: this(httpMethod, path, binaryMethod, null, null) {}
public BinaryStreamHandler(string httpMethod, string path, BinaryMethod binaryMethod, string name, string description)
: base(httpMethod, path, name, description)
{
m_method = binaryMethod;
}
public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
byte[] data = ReadFully(request);
@ -45,12 +54,6 @@ namespace OpenSim.Framework.Servers.HttpServer
return Encoding.UTF8.GetBytes(responseString);
}
public BinaryStreamHandler(string httpMethod, string path, BinaryMethod binaryMethod)
: base(httpMethod, path)
{
m_method = binaryMethod;
}
private static byte[] ReadFully(Stream stream)
{
byte[] buffer = new byte[1024];

View File

@ -128,11 +128,5 @@ namespace OpenSim.Framework.Servers.HttpServer
/// <param name="value">string containing the header field
/// value</param>
void AddHeader(string key, string value);
/// <summary>
/// Send the response back to the remote client
/// </summary>
void Send();
}
}

View File

@ -32,6 +32,25 @@ namespace OpenSim.Framework.Servers.HttpServer
{
public interface IRequestHandler
{
/// <summary>
/// Name for this handler.
/// </summary>
/// <remarks>
/// Used for diagnostics. The path doesn't always describe what the handler does. Can be null if none
/// specified.
/// </remarks>
string Name { get; }
/// <summary>
/// Description for this handler.
/// </summary>
/// <remarks>
/// Used for diagnostics. The path doesn't always describe what the handler does. Can be null if none
/// specified.
/// </remarks>
string Description { get; }
// Return response content type
string ContentType { get; }

View File

@ -321,13 +321,12 @@ namespace OpenSim.Framework.Servers.HttpServer
{
_httpResponse.Body.Flush();
_httpResponse.Send();
}
public void FreeContext()
{
if (_httpClientContext != null)
_httpClientContext.Close();
}
}
}

View File

@ -28,6 +28,7 @@
using System;
using System.Collections;
using OpenMetaverse;
namespace OpenSim.Framework.Servers.HttpServer
{
public delegate void RequestMethod(UUID requestID, Hashtable request);
@ -44,7 +45,11 @@ namespace OpenSim.Framework.Servers.HttpServer
public NoEventsMethod NoEvents;
public RequestMethod Request;
public UUID Id;
public PollServiceEventArgs(RequestMethod pRequest, HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,UUID pId)
public PollServiceEventArgs(
RequestMethod pRequest,
HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,
UUID pId)
{
Request = pRequest;
HasEvents = pHasEvents;

View File

@ -31,7 +31,6 @@ using OpenMetaverse;
namespace OpenSim.Framework.Servers.HttpServer
{
public class PollServiceHttpRequest
{
public readonly PollServiceEventArgs PollServiceArgs;
@ -39,7 +38,9 @@ namespace OpenSim.Framework.Servers.HttpServer
public readonly IHttpRequest Request;
public readonly int RequestTime;
public readonly UUID RequestID;
public PollServiceHttpRequest(PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest)
public PollServiceHttpRequest(
PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest)
{
PollServiceArgs = pPollServiceArgs;
HttpContext = pHttpContext;

View File

@ -66,6 +66,7 @@ namespace OpenSim.Framework.Servers.HttpServer
ThreadPriority.Normal,
false,
true,
null,
int.MaxValue);
}
@ -75,6 +76,7 @@ namespace OpenSim.Framework.Servers.HttpServer
ThreadPriority.Normal,
false,
true,
null,
1000 * 60 * 10);
}
@ -138,9 +140,8 @@ namespace OpenSim.Framework.Servers.HttpServer
foreach (object o in m_requests)
{
PollServiceHttpRequest req = (PollServiceHttpRequest) o;
m_server.DoHTTPGruntWork(
req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id),
new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext));
PollServiceWorkerThread.DoHTTPGruntWork(
m_server, req, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
}
m_requests.Clear();
@ -149,6 +150,7 @@ namespace OpenSim.Framework.Servers.HttpServer
{
t.Abort();
}
m_running = false;
}
}

View File

@ -90,15 +90,16 @@ namespace OpenSim.Framework.Servers.HttpServer
}
Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id, str.ReadToEnd());
m_server.DoHTTPGruntWork(responsedata,
new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request),req.HttpContext));
DoHTTPGruntWork(m_server, req, responsedata);
}
else
{
if ((Environment.TickCount - req.RequestTime) > m_timeout)
{
m_server.DoHTTPGruntWork(req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id),
new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request),req.HttpContext));
DoHTTPGruntWork(
m_server,
req,
req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
}
else
{
@ -119,5 +120,45 @@ namespace OpenSim.Framework.Servers.HttpServer
{
m_request.Enqueue(pPollServiceHttpRequest);
}
/// <summary>
/// FIXME: This should be part of BaseHttpServer
/// </summary>
internal static void DoHTTPGruntWork(BaseHttpServer server, PollServiceHttpRequest req, Hashtable responsedata)
{
OSHttpResponse response
= new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext);
byte[] buffer = server.DoHTTPGruntWork(responsedata, response);
response.SendChunked = false;
response.ContentLength64 = buffer.Length;
response.ContentEncoding = Encoding.UTF8;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
m_log.Warn(string.Format("[POLL SERVICE WORKER THREAD]: Error ", ex));
}
finally
{
//response.OutputStream.Close();
try
{
response.OutputStream.Flush();
response.Send();
//if (!response.KeepAlive && response.ReuseContext)
// response.FreeContext();
}
catch (Exception e)
{
m_log.Warn(String.Format("[POLL SERVICE WORKER THREAD]: Error ", e));
}
}
}
}
}

View File

@ -39,7 +39,11 @@ namespace OpenSim.Framework.Servers.HttpServer
private RestDeserialiseMethod<TRequest, TResponse> m_method;
public RestDeserialiseHandler(string httpMethod, string path, RestDeserialiseMethod<TRequest, TResponse> method)
: base(httpMethod, path)
: this(httpMethod, path, method, null, null) {}
public RestDeserialiseHandler(
string httpMethod, string path, RestDeserialiseMethod<TRequest, TResponse> method, string name, string description)
: base(httpMethod, path, name, description)
{
m_method = method;
}

View File

@ -38,19 +38,25 @@ namespace OpenSim.Framework.Servers.HttpServer
get { return m_dhttpMethod; }
}
public override Hashtable Handle(string path, Hashtable request)
{
string param = GetParam(path);
request.Add("param", param);
request.Add("path", path);
return m_dhttpMethod(request);
}
public RestHTTPHandler(string httpMethod, string path, GenericHTTPMethod dhttpMethod)
: base(httpMethod, path)
{
m_dhttpMethod = dhttpMethod;
}
public RestHTTPHandler(
string httpMethod, string path, GenericHTTPMethod dhttpMethod, string name, string description)
: base(httpMethod, path, name, description)
{
m_dhttpMethod = dhttpMethod;
}
public override Hashtable Handle(string path, Hashtable request)
{
string param = GetParam(path);
request.Add("param", param);
request.Add("path", path);
return m_dhttpMethod(request);
}
}
}

View File

@ -39,6 +39,15 @@ namespace OpenSim.Framework.Servers.HttpServer
get { return m_restMethod; }
}
public RestStreamHandler(string httpMethod, string path, RestMethod restMethod)
: this(httpMethod, path, restMethod, null, null) {}
public RestStreamHandler(string httpMethod, string path, RestMethod restMethod, string name, string description)
: base(httpMethod, path, name, description)
{
m_restMethod = restMethod;
}
public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
Encoding encoding = Encoding.UTF8;
@ -52,10 +61,5 @@ namespace OpenSim.Framework.Servers.HttpServer
return Encoding.UTF8.GetBytes(responseString);
}
public RestStreamHandler(string httpMethod, string path, RestMethod restMethod) : base(httpMethod, path)
{
m_restMethod = restMethod;
}
}
}

View File

@ -25,57 +25,262 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Net;
using System.Text;
using log4net;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Servers.HttpServer;
namespace OpenSim.Framework.Servers
{
public class MainServer
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static BaseHttpServer instance = null;
private static Dictionary<uint, BaseHttpServer> m_Servers =
new Dictionary<uint, BaseHttpServer>();
private static Dictionary<uint, BaseHttpServer> m_Servers = new Dictionary<uint, BaseHttpServer>();
/// <summary>
/// Control the printing of certain debug messages.
/// </summary>
/// <remarks>
/// If DebugLevel >= 1, then short warnings are logged when receiving bad input data.
/// If DebugLevel >= 2, then long warnings are logged when receiving bad input data.
/// If DebugLevel >= 3, then short notices about all incoming non-poll HTTP requests are logged.
/// </remarks>
public static int DebugLevel
{
get { return s_debugLevel; }
set
{
s_debugLevel = value;
lock (m_Servers)
foreach (BaseHttpServer server in m_Servers.Values)
server.DebugLevel = s_debugLevel;
}
}
private static int s_debugLevel;
/// <summary>
/// Set the main HTTP server instance.
/// </summary>
/// <remarks>
/// This will be used to register all handlers that listen to the default port.
/// </remarks>
/// <exception cref='Exception'>
/// Thrown if the HTTP server has not already been registered via AddHttpServer()
/// </exception>
public static BaseHttpServer Instance
{
get { return instance; }
set { instance = value; }
set
{
lock (m_Servers)
if (!m_Servers.ContainsValue(value))
throw new Exception("HTTP server must already have been registered to be set as the main instance");
instance = value;
}
}
public static IHttpServer GetHttpServer(uint port)
/// <summary>
/// Get all the registered servers.
/// </summary>
/// <remarks>
/// Returns a copy of the dictionary so this can be iterated through without locking.
/// </remarks>
/// <value></value>
public static Dictionary<uint, BaseHttpServer> Servers
{
return GetHttpServer(port,null);
get { return new Dictionary<uint, BaseHttpServer>(m_Servers); }
}
public static void RegisterHttpConsoleCommands(ICommandConsole console)
{
console.Commands.AddCommand(
"Comms", false, "show http-handlers",
"show http-handlers",
"Show all registered http handlers", HandleShowHttpHandlersCommand);
console.Commands.AddCommand(
"Debug", false, "debug http", "debug http [<level>]",
"Turn on inbound non-poll http request debugging.",
"If level <= 0, then no extra logging is done.\n"
+ "If level >= 1, then short warnings are logged when receiving bad input data.\n"
+ "If level >= 2, then long warnings are logged when receiving bad input data.\n"
+ "If level >= 3, then short notices about all incoming non-poll HTTP requests are logged.\n"
+ "If level >= 4, then a sample from the beginning of the incoming data is logged.\n"
+ "If level >= 5, then the entire incoming data is logged.\n"
+ "If no level is specified then the current level is returned.",
HandleDebugHttpCommand);
}
/// <summary>
/// Turn on some debugging values for OpenSim.
/// </summary>
/// <param name="args"></param>
private static void HandleDebugHttpCommand(string module, string[] args)
{
if (args.Length == 3)
{
int newDebug;
if (int.TryParse(args[2], out newDebug))
{
MainServer.DebugLevel = newDebug;
MainConsole.Instance.OutputFormat("Debug http level set to {0}", newDebug);
}
}
else if (args.Length == 2)
{
MainConsole.Instance.OutputFormat("Current debug http level is {0}", MainServer.DebugLevel);
}
else
{
MainConsole.Instance.Output("Usage: debug http 0..5");
}
}
private static void HandleShowHttpHandlersCommand(string module, string[] args)
{
if (args.Length != 2)
{
MainConsole.Instance.Output("Usage: show http-handlers");
return;
}
StringBuilder handlers = new StringBuilder();
lock (m_Servers)
{
foreach (BaseHttpServer httpServer in m_Servers.Values)
{
handlers.AppendFormat(
"Registered HTTP Handlers for server at {0}:{1}\n", httpServer.ListenIPAddress, httpServer.Port);
handlers.AppendFormat("* XMLRPC:\n");
foreach (String s in httpServer.GetXmlRpcHandlerKeys())
handlers.AppendFormat("\t{0}\n", s);
handlers.AppendFormat("* HTTP:\n");
List<String> poll = httpServer.GetPollServiceHandlerKeys();
foreach (String s in httpServer.GetHTTPHandlerKeys())
handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty));
handlers.AppendFormat("* Agent:\n");
foreach (String s in httpServer.GetAgentHandlerKeys())
handlers.AppendFormat("\t{0}\n", s);
handlers.AppendFormat("* LLSD:\n");
foreach (String s in httpServer.GetLLSDHandlerKeys())
handlers.AppendFormat("\t{0}\n", s);
handlers.AppendFormat("* StreamHandlers ({0}):\n", httpServer.GetStreamHandlerKeys().Count);
foreach (String s in httpServer.GetStreamHandlerKeys())
handlers.AppendFormat("\t{0}\n", s);
handlers.Append("\n");
}
}
MainConsole.Instance.Output(handlers.ToString());
}
/// <summary>
/// Register an already started HTTP server to the collection of known servers.
/// </summary>
/// <param name='server'></param>
public static void AddHttpServer(BaseHttpServer server)
{
m_Servers.Add(server.Port, server);
lock (m_Servers)
{
if (m_Servers.ContainsKey(server.Port))
throw new Exception(string.Format("HTTP server for port {0} already exists.", server.Port));
m_Servers.Add(server.Port, server);
}
}
/// <summary>
/// Removes the http server listening on the given port.
/// </summary>
/// <remarks>
/// It is the responsibility of the caller to do clean up.
/// </remarks>
/// <param name='port'></param>
/// <returns></returns>
public static bool RemoveHttpServer(uint port)
{
lock (m_Servers)
return m_Servers.Remove(port);
}
/// <summary>
/// Does this collection of servers contain one with the given port?
/// </summary>
/// <remarks>
/// Unlike GetHttpServer, this will not instantiate a server if one does not exist on that port.
/// </remarks>
/// <param name='port'></param>
/// <returns>true if a server with the given port is registered, false otherwise.</returns>
public static bool ContainsHttpServer(uint port)
{
lock (m_Servers)
return m_Servers.ContainsKey(port);
}
/// <summary>
/// Get the default http server or an http server for a specific port.
/// </summary>
/// <remarks>
/// If the requested HTTP server doesn't already exist then a new one is instantiated and started.
/// </remarks>
/// <returns></returns>
/// <param name='port'>If 0 then the default HTTP server is returned.</param>
public static IHttpServer GetHttpServer(uint port)
{
return GetHttpServer(port, null);
}
/// <summary>
/// Get the default http server, an http server for a specific port
/// and/or an http server bound to a specific address
/// </summary>
/// <remarks>
/// If the requested HTTP server doesn't already exist then a new one is instantiated and started.
/// </remarks>
/// <returns></returns>
/// <param name='port'>If 0 then the default HTTP server is returned.</param>
/// <param name='ipaddr'>A specific IP address to bind to. If null then the default IP address is used.</param>
public static IHttpServer GetHttpServer(uint port, IPAddress ipaddr)
{
if (port == 0)
return Instance;
if (instance != null && port == Instance.Port)
return Instance;
if (m_Servers.ContainsKey(port))
lock (m_Servers)
{
if (m_Servers.ContainsKey(port))
return m_Servers[port];
m_Servers[port] = new BaseHttpServer(port);
if (ipaddr != null)
m_Servers[port].ListenIPAddress = ipaddr;
m_Servers[port].Start();
return m_Servers[port];
m_Servers[port] = new BaseHttpServer(port);
if (ipaddr != null)
m_Servers[port].ListenIPAddress = ipaddr;
m_log.InfoFormat("[MAIN HTTP SERVER]: Starting main http server on port {0}", port);
m_Servers[port].Start();
return m_Servers[port];
}
}
}
}

View File

@ -30,7 +30,7 @@ namespace OpenSim
public class VersionInfo
{
private const string VERSION_NUMBER = "0.7.3";
private const Flavour VERSION_FLAVOUR = Flavour.Dev;
private const Flavour VERSION_FLAVOUR = Flavour.Extended;
public enum Flavour
{
@ -39,7 +39,8 @@ namespace OpenSim
RC1,
RC2,
Release,
Post_Fixes
Post_Fixes,
Extended
}
public static string Version

View File

@ -26,8 +26,8 @@
*/
using System;
using System.Diagnostics;
using System.Text;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
@ -44,10 +44,18 @@ namespace OpenSim.Framework.Statistics
StringBuilder sb = new StringBuilder(Environment.NewLine);
sb.Append("MEMORY STATISTICS");
sb.Append(Environment.NewLine);
sb.Append(
string.Format(
"Allocated to OpenSim : {0} MB" + Environment.NewLine,
Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)));
sb.AppendFormat(
"Allocated to OpenSim objects: {0} MB\n",
Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
sb.AppendFormat(
"OpenSim object memory churn : {0} MB/s\n",
Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3));
sb.AppendFormat(
"Process memory : {0} MB\n",
Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0));
return sb.ToString();
}

View File

@ -34,14 +34,12 @@ namespace OpenSim.Framework.Statistics
{
private static AssetStatsCollector assetStats;
private static UserStatsCollector userStats;
private static SimExtraStatsCollector simExtraStats;
private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
public static AssetStatsCollector AssetStats { get { return assetStats; } }
public static UserStatsCollector UserStats { get { return userStats; } }
public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } }
private StatsManager() {}
/// <summary>
/// Start collecting statistics related to assets.
/// Should only be called once.
@ -63,16 +61,5 @@ namespace OpenSim.Framework.Statistics
return userStats;
}
/// <summary>
/// Start collecting extra sim statistics apart from those collected for the client.
/// Should only be called once.
/// </summary>
public static SimExtraStatsCollector StartCollectingSimExtraStats()
{
simExtraStats = new SimExtraStatsCollector();
return simExtraStats;
}
}
}

View File

@ -81,12 +81,15 @@ namespace OpenSim.Framework
private static uint nextXferID = 5000;
private static Random randomClass = new Random();
// Get a list of invalid file characters (OS dependent)
private static string regexInvalidFileChars = "[" + new String(Path.GetInvalidFileNameChars()) + "]";
private static string regexInvalidPathChars = "[" + new String(Path.GetInvalidPathChars()) + "]";
private static object XferLock = new object();
/// <summary>Thread pool used for Util.FireAndForget if
/// FireAndForgetMethod.SmartThreadPool is used</summary>
/// <summary>
/// Thread pool used for Util.FireAndForget if FireAndForgetMethod.SmartThreadPool is used
/// </summary>
private static SmartThreadPool m_ThreadPool;
// 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.
@ -144,8 +147,8 @@ namespace OpenSim.Framework
return lerp(y, lerp(x, a, b), lerp(x, c, d));
}
public static Encoding UTF8 = Encoding.UTF8;
public static Encoding UTF8NoBomEncoding = new UTF8Encoding(false);
/// <value>
/// Well known UUID for the blank texture used in the Linden SL viewer version 1.20 (and hopefully onwards)
@ -998,6 +1001,38 @@ namespace OpenSim.Framework
}
}
/// <summary>
/// Copy data from one stream to another, leaving the read position of both streams at the beginning.
/// </summary>
/// <param name='inputStream'>
/// Input stream. Must be seekable.
/// </param>
/// <exception cref='ArgumentException'>
/// Thrown if the input stream is not seekable.
/// </exception>
public static Stream Copy(Stream inputStream)
{
if (!inputStream.CanSeek)
throw new ArgumentException("Util.Copy(Stream inputStream) must receive an inputStream that can seek");
const int readSize = 256;
byte[] buffer = new byte[readSize];
MemoryStream ms = new MemoryStream();
int count = inputStream.Read(buffer, 0, readSize);
while (count > 0)
{
ms.Write(buffer, 0, count);
count = inputStream.Read(buffer, 0, readSize);
}
ms.Position = 0;
inputStream.Position = 0;
return ms;
}
public static XmlRpcResponse XmlRpcCommand(string url, string methodName, params object[] args)
{
return SendXmlRpcCommand(url, methodName, args);
@ -1234,8 +1269,7 @@ namespace OpenSim.Framework
public static string Base64ToString(string str)
{
UTF8Encoding encoder = new UTF8Encoding();
Decoder utf8Decode = encoder.GetDecoder();
Decoder utf8Decode = Encoding.UTF8.GetDecoder();
byte[] todecode_byte = Convert.FromBase64String(str);
int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
@ -1671,6 +1705,61 @@ namespace OpenSim.Framework
}
}
/// <summary>
/// Get a thread pool report.
/// </summary>
/// <returns></returns>
public static string GetThreadPoolReport()
{
string threadPoolUsed = null;
int maxThreads = 0;
int minThreads = 0;
int allocatedThreads = 0;
int inUseThreads = 0;
int waitingCallbacks = 0;
int completionPortThreads = 0;
StringBuilder sb = new StringBuilder();
if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
{
threadPoolUsed = "SmartThreadPool";
maxThreads = m_ThreadPool.MaxThreads;
minThreads = m_ThreadPool.MinThreads;
inUseThreads = m_ThreadPool.InUseThreads;
allocatedThreads = m_ThreadPool.ActiveThreads;
waitingCallbacks = m_ThreadPool.WaitingCallbacks;
}
else if (
FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem
|| FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
{
threadPoolUsed = "BuiltInThreadPool";
ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
int availableThreads;
ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
inUseThreads = maxThreads - availableThreads;
allocatedThreads = -1;
waitingCallbacks = -1;
}
if (threadPoolUsed != null)
{
sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
sb.AppendFormat("Max threads : {0}\n", maxThreads);
sb.AppendFormat("Min threads : {0}\n", minThreads);
sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
sb.AppendFormat("In use threads : {0}\n", inUseThreads);
sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
}
else
{
sb.AppendFormat("Thread pool not used\n");
}
return sb.ToString();
}
private static object SmartThreadPoolCallback(object o)
{
object[] array = (object[])o;
@ -1696,6 +1785,20 @@ namespace OpenSim.Framework
}
const Int32 EnvironmentTickCountMask = 0x3fffffff;
/// <summary>
/// Environment.TickCount is an int but it counts all 32 bits so it goes positive
/// and negative every 24.9 days. Subtracts the passed value (previously fetched by
/// 'EnvironmentTickCount()') and accounts for any wrapping.
/// </summary>
/// <param name="newValue"></param>
/// <param name="prevValue"></param>
/// <returns>subtraction of passed prevValue from current Environment.TickCount</returns>
public static Int32 EnvironmentTickCountSubtract(Int32 newValue, Int32 prevValue)
{
Int32 diff = newValue - prevValue;
return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1);
}
/// <summary>
/// Environment.TickCount is an int but it counts all 32 bits so it goes positive
/// and negative every 24.9 days. Subtracts the passed value (previously fetched by
@ -1704,8 +1807,7 @@ namespace OpenSim.Framework
/// <returns>subtraction of passed prevValue from current Environment.TickCount</returns>
public static Int32 EnvironmentTickCountSubtract(Int32 prevValue)
{
Int32 diff = EnvironmentTickCount() - prevValue;
return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1);
return EnvironmentTickCountSubtract(EnvironmentTickCount(), prevValue);
}
// Returns value of Tick Count A - TickCount B accounting for wrapping of TickCount

View File

@ -41,8 +41,8 @@ namespace OpenSim.Framework
/// <summary>Timer interval in milliseconds for the watchdog timer</summary>
const double WATCHDOG_INTERVAL_MS = 2500.0d;
/// <summary>Maximum timeout in milliseconds before a thread is considered dead</summary>
const int WATCHDOG_TIMEOUT_MS = 5000;
/// <summary>Default timeout in milliseconds before a thread is considered dead</summary>
public const int DEFAULT_WATCHDOG_TIMEOUT_MS = 5000;
[System.Diagnostics.DebuggerDisplay("{Thread.Name}")]
public class ThreadWatchdogInfo
@ -58,7 +58,7 @@ namespace OpenSim.Framework
public int FirstTick { get; private set; }
/// <summary>
/// First time this heartbeat update was invoked
/// Last time this heartbeat update was invoked
/// </summary>
public int LastTick { get; set; }
@ -77,6 +77,11 @@ namespace OpenSim.Framework
/// </summary>
public bool AlarmIfTimeout { get; set; }
/// <summary>
/// Method execute if alarm goes off. If null then no alarm method is fired.
/// </summary>
public Func<string> AlarmMethod { get; set; }
public ThreadWatchdogInfo(Thread thread, int timeout)
{
Thread = thread;
@ -87,27 +92,33 @@ namespace OpenSim.Framework
}
/// <summary>
/// This event is called whenever a tracked thread is stopped or
/// has not called UpdateThread() in time
/// </summary>
/// <param name="thread">The thread that has been identified as dead</param>
/// <param name="lastTick">The last time this thread called UpdateThread()</param>
public delegate void WatchdogTimeout(Thread thread, int lastTick);
/// <summary>This event is called whenever a tracked thread is
/// stopped or has not called UpdateThread() in time</summary>
public static event WatchdogTimeout OnWatchdogTimeout;
/// This event is called whenever a tracked thread is
/// stopped or has not called UpdateThread() in time<
/// /summary>
public static event Action<ThreadWatchdogInfo> OnWatchdogTimeout;
private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private static Dictionary<int, ThreadWatchdogInfo> m_threads;
private static System.Timers.Timer m_watchdogTimer;
/// <summary>
/// Last time the watchdog thread ran.
/// </summary>
/// <remarks>
/// Should run every WATCHDOG_INTERVAL_MS
/// </remarks>
public static int LastWatchdogThreadTick { get; private set; }
static Watchdog()
{
m_threads = new Dictionary<int, ThreadWatchdogInfo>();
m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS);
m_watchdogTimer.AutoReset = false;
m_watchdogTimer.Elapsed += WatchdogTimerElapsed;
// Set now so we don't get alerted on the first run
LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue;
m_watchdogTimer.Start();
}
@ -123,7 +134,7 @@ namespace OpenSim.Framework
public static Thread StartThread(
ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout)
{
return StartThread(start, name, priority, isBackground, alarmIfTimeout, WATCHDOG_TIMEOUT_MS);
return StartThread(start, name, priority, isBackground, alarmIfTimeout, null, DEFAULT_WATCHDOG_TIMEOUT_MS);
}
/// <summary>
@ -135,17 +146,24 @@ namespace OpenSim.Framework
/// <param name="isBackground">True to run this thread as a background
/// thread, otherwise false</param>
/// <param name="alarmIfTimeout">Trigger an alarm function is we have timed out</param>
/// <param name="alarmMethod">
/// Alarm method to call if alarmIfTimeout is true and there is a timeout.
/// Normally, this will just return some useful debugging information.
/// </param>
/// <param name="timeout">Number of milliseconds to wait until we issue a warning about timeout.</param>
/// <returns>The newly created Thread object</returns>
public static Thread StartThread(
ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout, int timeout)
ThreadStart start, string name, ThreadPriority priority, bool isBackground,
bool alarmIfTimeout, Func<string> alarmMethod, int timeout)
{
Thread thread = new Thread(start);
thread.Name = name;
thread.Priority = priority;
thread.IsBackground = isBackground;
ThreadWatchdogInfo twi = new ThreadWatchdogInfo(thread, timeout) { AlarmIfTimeout = alarmIfTimeout };
ThreadWatchdogInfo twi
= new ThreadWatchdogInfo(thread, timeout)
{ AlarmIfTimeout = alarmIfTimeout, AlarmMethod = alarmMethod };
m_log.DebugFormat(
"[WATCHDOG]: Started tracking thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId);
@ -258,7 +276,17 @@ namespace OpenSim.Framework
/// <param name="e"></param>
private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
WatchdogTimeout callback = OnWatchdogTimeout;
int now = Environment.TickCount & Int32.MaxValue;
int msElapsed = now - LastWatchdogThreadTick;
if (msElapsed > WATCHDOG_INTERVAL_MS * 2)
m_log.WarnFormat(
"[WATCHDOG]: {0} ms since Watchdog last ran. Interval should be approximately {1} ms",
msElapsed, WATCHDOG_INTERVAL_MS);
LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue;
Action<ThreadWatchdogInfo> callback = OnWatchdogTimeout;
if (callback != null)
{
@ -266,8 +294,6 @@ namespace OpenSim.Framework
lock (m_threads)
{
int now = Environment.TickCount & Int32.MaxValue;
foreach (ThreadWatchdogInfo threadInfo in m_threads.Values)
{
if (threadInfo.Thread.ThreadState == ThreadState.Stopped)
@ -296,9 +322,12 @@ namespace OpenSim.Framework
if (callbackInfos != null)
foreach (ThreadWatchdogInfo callbackInfo in callbackInfos)
callback(callbackInfo.Thread, callbackInfo.LastTick);
callback(callbackInfo);
}
if (MemoryWatchdog.Enabled)
MemoryWatchdog.Update();
m_watchdogTimer.Start();
}
}

View File

@ -53,45 +53,36 @@ namespace OpenSim.Framework
LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
private static int m_requestNumber = 0;
/// <summary>
/// Request number for diagnostic purposes.
/// </summary>
public static int RequestNumber = 0;
// this is the header field used to communicate the local request id
// used for performance and debugging
/// <summary>
/// this is the header field used to communicate the local request id
/// used for performance and debugging
/// </summary>
public const string OSHeaderRequestID = "opensim-request-id";
// number of milliseconds a call can take before it is considered
// a "long" call for warning & debugging purposes
public const int LongCallTime = 500;
/// <summary>
/// Number of milliseconds a call can take before it is considered
/// a "long" call for warning & debugging purposes
/// </summary>
public const int LongCallTime = 3000;
// /// <summary>
// /// Send LLSD to an HTTP client in application/llsd+json form
// /// </summary>
// /// <param name="response">HTTP response to send the data in</param>
// /// <param name="body">LLSD to send to the client</param>
// public static void SendJSONResponse(OSHttpResponse response, OSDMap body)
// {
// byte[] responseData = Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(body));
//
// response.ContentEncoding = Encoding.UTF8;
// response.ContentLength = responseData.Length;
// response.ContentType = "application/llsd+json";
// response.Body.Write(responseData, 0, responseData.Length);
// }
//
// /// <summary>
// /// Send LLSD to an HTTP client in application/llsd+xml form
// /// </summary>
// /// <param name="response">HTTP response to send the data in</param>
// /// <param name="body">LLSD to send to the client</param>
// public static void SendXMLResponse(OSHttpResponse response, OSDMap body)
// {
// byte[] responseData = OSDParser.SerializeLLSDXmlBytes(body);
//
// response.ContentEncoding = Encoding.UTF8;
// response.ContentLength = responseData.Length;
// response.ContentType = "application/llsd+xml";
// response.Body.Write(responseData, 0, responseData.Length);
// }
/// <summary>
/// The maximum length of any data logged because of a long request time.
/// </summary>
/// <remarks>
/// This is to truncate any really large post data, such as an asset. In theory, the first section should
/// give us useful information about the call (which agent it relates to if applicable, etc.).
/// </remarks>
public const int MaxRequestDiagLength = 100;
/// <summary>
/// Dictionary of end points
/// </summary>
private static Dictionary<string,object> m_endpointSerializer = new Dictionary<string,object>();
/// <summary>
/// Make a GET or GET-like request to a web service that returns LLSD
@ -166,12 +157,14 @@ namespace OpenSim.Framework
public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed)
{
int reqnum = m_requestNumber++;
int reqnum = RequestNumber++;
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
string errorMessage = "unknown error";
int tickstart = Util.EnvironmentTickCount();
int tickdata = 0;
string strBuffer = null;
try
{
@ -186,7 +179,7 @@ namespace OpenSim.Framework
// If there is some input, write it into the request
if (data != null)
{
string strBuffer = OSDParser.SerializeJsonString(data);
strBuffer = OSDParser.SerializeJsonString(data);
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer);
if (compressed)
@ -246,14 +239,23 @@ namespace OpenSim.Framework
}
finally
{
// This just dumps a warning for any operation that takes more than 100 ms
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
if (tickdiff > LongCallTime)
m_log.DebugFormat("[WEB UTIL]: osd request <{0}> (URI:{1}, METHOD:{2}) took {3}ms overall, {4}ms writing",
reqnum,url,method,tickdiff,tickdata);
m_log.InfoFormat(
"[OSD REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
reqnum,
method,
url,
tickdiff,
tickdata,
strBuffer != null
? (strBuffer.Length > MaxRequestDiagLength ? strBuffer.Remove(MaxRequestDiagLength) : strBuffer)
: "");
}
m_log.DebugFormat("[WEB UTIL]: <{0}> osd request for {1}, method {2} FAILED: {3}", reqnum, url, method, errorMessage);
m_log.DebugFormat(
"[WEB UTIL]: <{0}> osd request for {1}, method {2} FAILED: {3}", reqnum, url, method, errorMessage);
return ErrorResponseMap(errorMessage);
}
@ -314,17 +316,17 @@ namespace OpenSim.Framework
public static OSDMap ServiceFormRequest(string url, NameValueCollection data, int timeout)
{
int reqnum = m_requestNumber++;
int reqnum = RequestNumber++;
string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown";
// m_log.DebugFormat("[WEB UTIL]: <{0}> start form request for {1}, method {2}",reqnum,url,method);
string errorMessage = "unknown error";
int tickstart = Util.EnvironmentTickCount();
int tickdata = 0;
string queryString = null;
try
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Method = "POST";
request.Timeout = timeout;
@ -335,7 +337,7 @@ namespace OpenSim.Framework
if (data != null)
{
string queryString = BuildQueryString(data);
queryString = BuildQueryString(data);
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(queryString);
request.ContentLength = buffer.Length;
@ -378,11 +380,20 @@ namespace OpenSim.Framework
{
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
if (tickdiff > LongCallTime)
m_log.InfoFormat("[WEB UTIL]: form request <{0}> (URI:{1}, METHOD:{2}) took {3}ms overall, {4}ms writing",
reqnum,url,method,tickdiff,tickdata);
m_log.InfoFormat(
"[SERVICE FORM]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
reqnum,
method,
url,
tickdiff,
tickdata,
queryString != null
? (queryString.Length > MaxRequestDiagLength) ? queryString.Remove(MaxRequestDiagLength) : queryString
: "");
}
m_log.WarnFormat("[WEB UTIL]: <{0}> form request failed: {1}",reqnum,errorMessage);
m_log.WarnFormat("[SERVICE FORM]: <{0}> form request to {1} failed: {2}", reqnum, url, errorMessage);
return ErrorResponseMap(errorMessage);
}
@ -655,8 +666,6 @@ namespace OpenSim.Framework
return new string[0];
}
}
public static class AsynchronousRestObjectRequester
@ -679,6 +688,12 @@ namespace OpenSim.Framework
public static void MakeRequest<TRequest, TResponse>(string verb,
string requestUrl, TRequest obj, Action<TResponse> action)
{
int reqnum = WebUtil.RequestNumber++;
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
int tickstart = Util.EnvironmentTickCount();
int tickdata = 0;
// m_log.DebugFormat("[ASYNC REQUEST]: Starting {0} {1}", verb, requestUrl);
Type type = typeof(TRequest);
@ -689,12 +704,13 @@ namespace OpenSim.Framework
XmlSerializer deserializer = new XmlSerializer(typeof(TResponse));
request.Method = verb;
MemoryStream buffer = null;
if (verb == "POST")
{
request.ContentType = "text/xml";
MemoryStream buffer = new MemoryStream();
buffer = new MemoryStream();
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
@ -716,6 +732,9 @@ namespace OpenSim.Framework
requestStream.Write(buffer.ToArray(), 0, length);
requestStream.Close();
// capture how much time was spent writing
tickdata = Util.EnvironmentTickCountSubtract(tickstart);
request.BeginGetResponse(delegate(IAsyncResult ar)
{
response = request.EndGetResponse(ar);
@ -741,83 +760,108 @@ namespace OpenSim.Framework
}, null);
}, null);
return;
}
request.BeginGetResponse(delegate(IAsyncResult res2)
else
{
try
request.BeginGetResponse(delegate(IAsyncResult res2)
{
// If the server returns a 404, this appears to trigger a System.Net.WebException even though that isn't
// documented in MSDN
response = request.EndGetResponse(res2);
Stream respStream = null;
try
{
respStream = response.GetResponseStream();
deserial = (TResponse)deserializer.Deserialize(respStream);
}
catch (System.InvalidOperationException)
{
}
finally
{
respStream.Close();
response.Close();
}
}
catch (WebException e)
{
if (e.Status == WebExceptionStatus.ProtocolError)
{
if (e.Response is HttpWebResponse)
{
HttpWebResponse httpResponse = (HttpWebResponse)e.Response;
// If the server returns a 404, this appears to trigger a System.Net.WebException even though that isn't
// documented in MSDN
response = request.EndGetResponse(res2);
if (httpResponse.StatusCode != HttpStatusCode.NotFound)
{
// We don't appear to be handling any other status codes, so log these feailures to that
// people don't spend unnecessary hours hunting phantom bugs.
m_log.DebugFormat(
"[ASYNC REQUEST]: Request {0} {1} failed with unexpected status code {2}",
verb, requestUrl, httpResponse.StatusCode);
}
Stream respStream = null;
try
{
respStream = response.GetResponseStream();
deserial = (TResponse)deserializer.Deserialize(respStream);
}
catch (System.InvalidOperationException)
{
}
finally
{
respStream.Close();
response.Close();
}
}
else
catch (WebException e)
{
m_log.ErrorFormat("[ASYNC REQUEST]: Request {0} {1} failed with status {2} and message {3}", verb, requestUrl, e.Status, e.Message);
if (e.Status == WebExceptionStatus.ProtocolError)
{
if (e.Response is HttpWebResponse)
{
HttpWebResponse httpResponse = (HttpWebResponse)e.Response;
if (httpResponse.StatusCode != HttpStatusCode.NotFound)
{
// We don't appear to be handling any other status codes, so log these feailures to that
// people don't spend unnecessary hours hunting phantom bugs.
m_log.DebugFormat(
"[ASYNC REQUEST]: Request {0} {1} failed with unexpected status code {2}",
verb, requestUrl, httpResponse.StatusCode);
}
}
}
else
{
m_log.ErrorFormat(
"[ASYNC REQUEST]: Request {0} {1} failed with status {2} and message {3}",
verb, requestUrl, e.Status, e.Message);
}
}
}
catch (Exception e)
catch (Exception e)
{
m_log.ErrorFormat(
"[ASYNC REQUEST]: Request {0} {1} failed with exception {2}{3}",
verb, requestUrl, e.Message, e.StackTrace);
}
// m_log.DebugFormat("[ASYNC REQUEST]: Received {0}", deserial.ToString());
try
{
action(deserial);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[ASYNC REQUEST]: Request {0} {1} callback failed with exception {2}{3}",
verb, requestUrl, e.Message, e.StackTrace);
}
}, null);
}
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
if (tickdiff > WebUtil.LongCallTime)
{
string originalRequest = null;
if (buffer != null)
{
m_log.ErrorFormat("[ASYNC REQUEST]: Request {0} {1} failed with exception {2}", verb, requestUrl, e);
originalRequest = Encoding.UTF8.GetString(buffer.ToArray());
if (originalRequest.Length > WebUtil.MaxRequestDiagLength)
originalRequest = originalRequest.Remove(WebUtil.MaxRequestDiagLength);
}
// m_log.DebugFormat("[ASYNC REQUEST]: Received {0}", deserial.ToString());
try
{
action(deserial);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[ASYNC REQUEST]: Request {0} {1} callback failed with exception {2}", verb, requestUrl, e);
}
}, null);
m_log.InfoFormat(
"[ASYNC REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
reqnum,
verb,
requestUrl,
tickdiff,
tickdata,
originalRequest);
}
}
}
public static class SynchronousRestFormsRequester
{
private static readonly ILog m_log =
LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// Perform a synchronous REST request.
@ -831,6 +875,12 @@ namespace OpenSim.Framework
/// the request. You'll want to make sure you deal with this as they're not uncommon</exception>
public static string MakeRequest(string verb, string requestUrl, string obj)
{
int reqnum = WebUtil.RequestNumber++;
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
int tickstart = Util.EnvironmentTickCount();
int tickdata = 0;
WebRequest request = WebRequest.Create(requestUrl);
request.Method = verb;
string respstring = String.Empty;
@ -859,12 +909,16 @@ namespace OpenSim.Framework
}
catch (Exception e)
{
m_log.DebugFormat("[FORMS]: exception occured on sending request to {0}: " + e.ToString(), requestUrl);
m_log.DebugFormat(
"[FORMS]: exception occured {0} {1}: {2}{3}", verb, requestUrl, e.Message, e.StackTrace);
}
finally
{
if (requestStream != null)
requestStream.Close();
// capture how much time was spent writing
tickdata = Util.EnvironmentTickCountSubtract(tickstart);
}
}
@ -885,7 +939,9 @@ namespace OpenSim.Framework
}
catch (Exception e)
{
m_log.DebugFormat("[FORMS]: exception occured on receiving reply " + e.ToString());
m_log.DebugFormat(
"[FORMS]: Exception occured on receiving {0} {1}: {2}{3}",
verb, requestUrl, e.Message, e.StackTrace);
}
finally
{
@ -898,9 +954,21 @@ namespace OpenSim.Framework
catch (System.InvalidOperationException)
{
// This is what happens when there is invalid XML
m_log.DebugFormat("[FORMS]: InvalidOperationException on receiving request");
m_log.DebugFormat("[FORMS]: InvalidOperationException on receiving {0} {1}", verb, requestUrl);
}
}
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
if (tickdiff > WebUtil.LongCallTime)
m_log.InfoFormat(
"[FORMS]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
reqnum,
verb,
requestUrl,
tickdiff,
tickdata,
obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj);
return respstring;
}
}
@ -923,17 +991,24 @@ namespace OpenSim.Framework
/// the request. You'll want to make sure you deal with this as they're not uncommon</exception>
public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj)
{
int reqnum = WebUtil.RequestNumber++;
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
int tickstart = Util.EnvironmentTickCount();
int tickdata = 0;
Type type = typeof(TRequest);
TResponse deserial = default(TResponse);
WebRequest request = WebRequest.Create(requestUrl);
request.Method = verb;
MemoryStream buffer = null;
if ((verb == "POST") || (verb == "PUT"))
{
request.ContentType = "text/xml";
MemoryStream buffer = new MemoryStream();
buffer = new MemoryStream();
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
@ -956,13 +1031,19 @@ namespace OpenSim.Framework
}
catch (Exception e)
{
m_log.DebugFormat("[SynchronousRestObjectRequester]: exception in sending data to {0}: {1}", requestUrl, e);
m_log.DebugFormat(
"[SynchronousRestObjectRequester]: Exception in making request {0} {1}: {2}{3}",
verb, requestUrl, e.Message, e.StackTrace);
return deserial;
}
finally
{
if (requestStream != null)
requestStream.Close();
// capture how much time was spent writing
tickdata = Util.EnvironmentTickCountSubtract(tickstart);
}
}
@ -978,7 +1059,11 @@ namespace OpenSim.Framework
respStream.Close();
}
else
m_log.DebugFormat("[SynchronousRestObjectRequester]: Oops! no content found in response stream from {0} {1}", requestUrl, verb);
{
m_log.DebugFormat(
"[SynchronousRestObjectRequester]: Oops! no content found in response stream from {0} {1}",
verb, requestUrl);
}
}
}
catch (WebException e)
@ -989,17 +1074,44 @@ namespace OpenSim.Framework
return deserial;
else
m_log.ErrorFormat(
"[SynchronousRestObjectRequester]: WebException {0} {1} {2} {3}",
requestUrl, typeof(TResponse).ToString(), e.Message, e.StackTrace);
"[SynchronousRestObjectRequester]: WebException for {0} {1} {2}: {3} {4}",
verb, requestUrl, typeof(TResponse).ToString(), e.Message, e.StackTrace);
}
catch (System.InvalidOperationException)
{
// This is what happens when there is invalid XML
m_log.DebugFormat("[SynchronousRestObjectRequester]: Invalid XML {0} {1}", requestUrl, typeof(TResponse).ToString());
m_log.DebugFormat(
"[SynchronousRestObjectRequester]: Invalid XML from {0} {1} {2}",
verb, requestUrl, typeof(TResponse).ToString());
}
catch (Exception e)
{
m_log.DebugFormat("[SynchronousRestObjectRequester]: Exception on response from {0} {1}", requestUrl, e);
m_log.DebugFormat(
"[SynchronousRestObjectRequester]: Exception on response from {0} {1}: {2}{3}",
verb, requestUrl, e.Message, e.StackTrace);
}
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
if (tickdiff > WebUtil.LongCallTime)
{
string originalRequest = null;
if (buffer != null)
{
originalRequest = Encoding.UTF8.GetString(buffer.ToArray());
if (originalRequest.Length > WebUtil.MaxRequestDiagLength)
originalRequest = originalRequest.Remove(WebUtil.MaxRequestDiagLength);
}
m_log.InfoFormat(
"[SynchronousRestObjectRequester]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
reqnum,
verb,
requestUrl,
tickdiff,
tickdata,
originalRequest);
}
return deserial;

View File

@ -92,9 +92,14 @@ namespace OpenSim
m_log.Info("[OPENSIM MAIN]: configured log4net using default OpenSim.exe.config");
}
m_log.DebugFormat(
m_log.InfoFormat(
"[OPENSIM MAIN]: System Locale is {0}", System.Threading.Thread.CurrentThread.CurrentCulture);
string monoThreadsPerCpu = System.Environment.GetEnvironmentVariable("MONO_THREADS_PER_CPU");
m_log.InfoFormat(
"[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}", monoThreadsPerCpu ?? "unset");
// Increase the number of IOCP threads available. Mono defaults to a tragically low number
int workerThreads, iocpThreads;
System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
@ -109,7 +114,6 @@ namespace OpenSim
// Check if the system is compatible with OpenSimulator.
// Ensures that the minimum system requirements are met
m_log.Info("Performing compatibility checks... \n");
string supported = String.Empty;
if (Util.IsEnvironmentSupported(ref supported))
{

View File

@ -28,12 +28,14 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Timers;
using log4net;
using NDesk.Options;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
@ -194,9 +196,9 @@ namespace OpenSim
PrintFileToConsole("startuplogo.txt");
// For now, start at the 'root' level by default
if (m_sceneManager.Scenes.Count == 1) // If there is only one region, select it
if (SceneManager.Scenes.Count == 1) // If there is only one region, select it
ChangeSelectedRegion("region",
new string[] {"change", "region", m_sceneManager.Scenes[0].RegionInfo.RegionName});
new string[] {"change", "region", SceneManager.Scenes[0].RegionInfo.RegionName});
else
ChangeSelectedRegion("region", new string[] {"change", "region", "root"});
@ -225,12 +227,14 @@ namespace OpenSim
/// </summary>
private void RegisterConsoleCommands()
{
m_console.Commands.AddCommand("region", false, "force update",
MainServer.RegisterHttpConsoleCommands(m_console);
m_console.Commands.AddCommand("Objects", false, "force update",
"force update",
"Force the update of all objects on clients",
HandleForceUpdate);
m_console.Commands.AddCommand("region", false, "debug packet",
m_console.Commands.AddCommand("Debug", false, "debug packet",
"debug packet <level> [<avatar-first-name> <avatar-last-name>]",
"Turn on packet debugging",
"If level > 255 then all incoming and outgoing packets are logged.\n"
@ -242,45 +246,37 @@ namespace OpenSim
+ "If an avatar name is given then only packets from that avatar are logged",
Debug);
m_console.Commands.AddCommand("region", false, "debug http",
"debug http <level>",
"Turn on inbound http request debugging for everything except the event queue (see debug eq).",
"If level >= 2 then the handler used to service the request is logged.\n"
+ "If level >= 1 then incoming HTTP requests are logged.\n"
+ "If level <= 0 then no extra http logging is done.\n",
Debug);
m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug);
m_console.Commands.AddCommand("region", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug);
m_console.Commands.AddCommand("region", false, "debug scene",
m_console.Commands.AddCommand("Debug", false, "debug scene",
"debug scene <scripting> <collisions> <physics>",
"Turn on scene debugging", Debug);
m_console.Commands.AddCommand("region", false, "change region",
m_console.Commands.AddCommand("General", false, "change region",
"change region <region name>",
"Change current console region", ChangeSelectedRegion);
m_console.Commands.AddCommand("region", false, "save xml",
m_console.Commands.AddCommand("Archiving", false, "save xml",
"save xml",
"Save a region's data in XML format", SaveXml);
m_console.Commands.AddCommand("region", false, "save xml2",
m_console.Commands.AddCommand("Archiving", false, "save xml2",
"save xml2",
"Save a region's data in XML2 format", SaveXml2);
m_console.Commands.AddCommand("region", false, "load xml",
m_console.Commands.AddCommand("Archiving", false, "load xml",
"load xml [-newIDs [<x> <y> <z>]]",
"Load a region's data from XML format", LoadXml);
m_console.Commands.AddCommand("region", false, "load xml2",
m_console.Commands.AddCommand("Archiving", false, "load xml2",
"load xml2",
"Load a region's data from XML2 format", LoadXml2);
m_console.Commands.AddCommand("region", false, "save prims xml2",
m_console.Commands.AddCommand("Archiving", false, "save prims xml2",
"save prims xml2 [<prim name> <file name>]",
"Save named prim to XML2", SavePrimsXml2);
m_console.Commands.AddCommand("region", false, "load oar",
m_console.Commands.AddCommand("Archiving", false, "load oar",
"load oar [--merge] [--skip-assets] [<OAR path>]",
"Load a region's data from an OAR archive.",
"--merge will merge the OAR with the existing scene." + Environment.NewLine
@ -289,7 +285,7 @@ namespace OpenSim
+ " If this is not given then the command looks for an OAR named region.oar in the current directory.",
LoadOar);
m_console.Commands.AddCommand("region", false, "save oar",
m_console.Commands.AddCommand("Archiving", false, "save oar",
//"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]",
"save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [<OAR path>]",
"Save a region's data to an OAR archive.",
@ -306,54 +302,53 @@ namespace OpenSim
+ " If this is not given then the oar is saved to region.oar in the current directory.",
SaveOar);
m_console.Commands.AddCommand("region", false, "edit scale",
m_console.Commands.AddCommand("Objects", false, "edit scale",
"edit scale <name> <x> <y> <z>",
"Change the scale of a named prim", HandleEditScale);
m_console.Commands.AddCommand("region", false, "kick user",
"kick user <first> <last> [message]",
"Kick a user off the simulator", KickUserCommand);
m_console.Commands.AddCommand("Users", false, "kick user",
"kick user <first> <last> [--force] [message]",
"Kick a user off the simulator",
"The --force option will kick the user without any checks to see whether it's already in the process of closing\n"
+ "Only use this option if you are sure the avatar is inactive and a normal kick user operation does not removed them",
KickUserCommand);
m_console.Commands.AddCommand("region", false, "show users",
m_console.Commands.AddCommand("Users", false, "show users",
"show users [full]",
"Show user data for users currently on the region",
"Without the 'full' option, only users actually on the region are shown."
+ " With the 'full' option child agents of users in neighbouring regions are also shown.",
HandleShow);
m_console.Commands.AddCommand("region", false, "show connections",
m_console.Commands.AddCommand("Comms", false, "show connections",
"show connections",
"Show connection data", HandleShow);
m_console.Commands.AddCommand("region", false, "show circuits",
m_console.Commands.AddCommand("Comms", false, "show circuits",
"show circuits",
"Show agent circuit data", HandleShow);
m_console.Commands.AddCommand("region", false, "show http-handlers",
"show http-handlers",
"Show all registered http handlers", HandleShow);
m_console.Commands.AddCommand("region", false, "show pending-objects",
m_console.Commands.AddCommand("Comms", false, "show pending-objects",
"show pending-objects",
"Show # of objects on the pending queues of all scene viewers", HandleShow);
m_console.Commands.AddCommand("region", false, "show modules",
m_console.Commands.AddCommand("General", false, "show modules",
"show modules",
"Show module data", HandleShow);
m_console.Commands.AddCommand("region", false, "show regions",
m_console.Commands.AddCommand("Regions", false, "show regions",
"show regions",
"Show region data", HandleShow);
m_console.Commands.AddCommand("region", false, "show ratings",
m_console.Commands.AddCommand("Regions", false, "show ratings",
"show ratings",
"Show rating data", HandleShow);
m_console.Commands.AddCommand("region", false, "backup",
m_console.Commands.AddCommand("Objects", false, "backup",
"backup",
"Persist currently unsaved object changes immediately instead of waiting for the normal persistence call.", RunCommand);
m_console.Commands.AddCommand("region", false, "create region",
m_console.Commands.AddCommand("Regions", false, "create region",
"create region [\"region name\"] <region_file.ini>",
"Create a new region.",
"The settings for \"region name\" are read from <region_file.ini>. Paths specified with <region_file.ini> are relative to your Regions directory, unless an absolute path is given."
@ -362,62 +357,57 @@ namespace OpenSim
+ "If <region_file.ini> does not exist, it will be created.",
HandleCreateRegion);
m_console.Commands.AddCommand("region", false, "restart",
m_console.Commands.AddCommand("Regions", false, "restart",
"restart",
"Restart all sims in this instance", RunCommand);
m_console.Commands.AddCommand("region", false, "config set",
m_console.Commands.AddCommand("General", false, "config set",
"config set <section> <key> <value>",
"Set a config option. In most cases this is not useful since changed parameters are not dynamically reloaded. Neither do changed parameters persist - you will have to change a config file manually and restart.", HandleConfig);
m_console.Commands.AddCommand("region", false, "config get",
m_console.Commands.AddCommand("General", false, "config get",
"config get [<section>] [<key>]",
"Synonym for config show",
HandleConfig);
m_console.Commands.AddCommand("region", false, "config show",
m_console.Commands.AddCommand("General", false, "config show",
"config show [<section>] [<key>]",
"Show config information",
"If neither section nor field are specified, then the whole current configuration is printed." + Environment.NewLine
+ "If a section is given but not a field, then all fields in that section are printed.",
HandleConfig);
m_console.Commands.AddCommand("region", false, "config save",
m_console.Commands.AddCommand("General", false, "config save",
"config save <path>",
"Save current configuration to a file at the given path", HandleConfig);
m_console.Commands.AddCommand("region", false, "command-script",
m_console.Commands.AddCommand("General", false, "command-script",
"command-script <script>",
"Run a command script from file", RunCommand);
m_console.Commands.AddCommand("region", false, "remove-region",
m_console.Commands.AddCommand("Regions", false, "remove-region",
"remove-region <name>",
"Remove a region from this simulator", RunCommand);
m_console.Commands.AddCommand("region", false, "delete-region",
m_console.Commands.AddCommand("Regions", false, "delete-region",
"delete-region <name>",
"Delete a region from disk", RunCommand);
m_console.Commands.AddCommand("region", false, "modules list",
m_console.Commands.AddCommand("General", false, "modules list",
"modules list",
"List modules", HandleModules);
m_console.Commands.AddCommand("region", false, "modules load",
m_console.Commands.AddCommand("General", false, "modules load",
"modules load <name>",
"Load a module", HandleModules);
m_console.Commands.AddCommand("region", false, "modules unload",
m_console.Commands.AddCommand("General", false, "modules unload",
"modules unload <name>",
"Unload a module", HandleModules);
m_console.Commands.AddCommand("region", false, "Add-InventoryHost",
"Add-InventoryHost <host>",
String.Empty, RunCommand);
m_console.Commands.AddCommand("region", false, "kill uuid",
m_console.Commands.AddCommand("Objects", false, "kill uuid",
"kill uuid <UUID>",
"Kill an object by UUID", KillUUID);
}
public override void ShutdownSpecific()
@ -442,12 +432,16 @@ namespace OpenSim
}
}
private void WatchdogTimeoutHandler(System.Threading.Thread thread, int lastTick)
private void WatchdogTimeoutHandler(Watchdog.ThreadWatchdogInfo twi)
{
int now = Environment.TickCount & Int32.MaxValue;
m_log.ErrorFormat("[WATCHDOG]: Timeout detected for thread \"{0}\". ThreadState={1}. Last tick was {2}ms ago",
thread.Name, thread.ThreadState, now - lastTick);
m_log.ErrorFormat(
"[WATCHDOG]: Timeout detected for thread \"{0}\". ThreadState={1}. Last tick was {2}ms ago. {3}",
twi.Thread.Name,
twi.Thread.ThreadState,
now - twi.LastTick,
twi.AlarmMethod != null ? string.Format("Data: {0}", twi.AlarmMethod()) : "");
}
#region Console Commands
@ -459,21 +453,27 @@ namespace OpenSim
/// <param name="cmdparams">name of avatar to kick</param>
private void KickUserCommand(string module, string[] cmdparams)
{
if (cmdparams.Length < 4)
bool force = false;
OptionSet options = new OptionSet().Add("f|force", delegate (string v) { force = v != null; });
List<string> mainParams = options.Parse(cmdparams);
if (mainParams.Count < 4)
return;
string alert = null;
if (cmdparams.Length > 4)
if (mainParams.Count > 4)
alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4));
IList agents = m_sceneManager.GetCurrentSceneAvatars();
IList agents = SceneManager.GetCurrentSceneAvatars();
foreach (ScenePresence presence in agents)
{
RegionInfo regionInfo = presence.Scene.RegionInfo;
if (presence.Firstname.ToLower().Contains(cmdparams[2].ToLower()) &&
presence.Lastname.ToLower().Contains(cmdparams[3].ToLower()))
if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) &&
presence.Lastname.ToLower().Contains(mainParams[3].ToLower()))
{
MainConsole.Instance.Output(
String.Format(
@ -486,10 +486,10 @@ namespace OpenSim
else
presence.ControllingClient.Kick("\nThe OpenSim manager kicked you out.\n");
// ...and close on our side
presence.Scene.IncomingCloseAgent(presence.UUID);
presence.Scene.IncomingCloseAgent(presence.UUID, force);
}
}
MainConsole.Instance.Output("");
}
@ -543,7 +543,7 @@ namespace OpenSim
private void HandleForceUpdate(string module, string[] args)
{
MainConsole.Instance.Output("Updating all clients");
m_sceneManager.ForceCurrentSceneClientUpdate();
SceneManager.ForceCurrentSceneClientUpdate();
}
/// <summary>
@ -555,7 +555,7 @@ namespace OpenSim
{
if (args.Length == 6)
{
m_sceneManager.HandleEditCommandOnCurrentScene(args);
SceneManager.HandleEditCommandOnCurrentScene(args);
}
else
{
@ -765,7 +765,7 @@ namespace OpenSim
case "load":
if (cmdparams.Length > 1)
{
foreach (Scene s in new ArrayList(m_sceneManager.Scenes))
foreach (Scene s in new ArrayList(SceneManager.Scenes))
{
MainConsole.Instance.Output(String.Format("Loading module: {0}", cmdparams[1]));
m_moduleLoader.LoadRegionModules(cmdparams[1], s);
@ -803,14 +803,14 @@ namespace OpenSim
case "backup":
MainConsole.Instance.Output("Triggering save of pending object updates to persistent store");
m_sceneManager.BackupCurrentScene();
SceneManager.BackupCurrentScene();
break;
case "remove-region":
string regRemoveName = CombineParams(cmdparams, 0);
Scene removeScene;
if (m_sceneManager.TryGetScene(regRemoveName, out removeScene))
if (SceneManager.TryGetScene(regRemoveName, out removeScene))
RemoveRegion(removeScene, false);
else
MainConsole.Instance.Output("No region with that name");
@ -820,23 +820,15 @@ namespace OpenSim
string regDeleteName = CombineParams(cmdparams, 0);
Scene killScene;
if (m_sceneManager.TryGetScene(regDeleteName, out killScene))
if (SceneManager.TryGetScene(regDeleteName, out killScene))
RemoveRegion(killScene, true);
else
MainConsole.Instance.Output("no region with that name");
break;
case "restart":
m_sceneManager.RestartCurrentScene();
SceneManager.RestartCurrentScene();
break;
case "Add-InventoryHost":
if (cmdparams.Length > 0)
{
MainConsole.Instance.Output("Not implemented.");
}
break;
}
}
@ -850,7 +842,7 @@ namespace OpenSim
{
string newRegionName = CombineParams(cmdparams, 2);
if (!m_sceneManager.TrySetCurrentScene(newRegionName))
if (!SceneManager.TrySetCurrentScene(newRegionName))
MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName));
}
else
@ -858,7 +850,7 @@ namespace OpenSim
MainConsole.Instance.Output("Usage: change region <region name>");
}
string regionName = (m_sceneManager.CurrentScene == null ? "root" : m_sceneManager.CurrentScene.RegionInfo.RegionName);
string regionName = (SceneManager.CurrentScene == null ? "root" : SceneManager.CurrentScene.RegionInfo.RegionName);
MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName));
// m_log.DebugFormat("Original prompt is {0}", m_consolePrompt);
@ -876,7 +868,7 @@ namespace OpenSim
});
m_console.DefaultPrompt = prompt;
m_console.ConsoleScene = m_sceneManager.CurrentScene;
m_console.ConsoleScene = SceneManager.CurrentScene;
}
/// <summary>
@ -900,7 +892,7 @@ namespace OpenSim
int newDebug;
if (int.TryParse(args[2], out newDebug))
{
m_sceneManager.SetDebugPacketLevelOnCurrentScene(newDebug, name);
SceneManager.SetDebugPacketLevelOnCurrentScene(newDebug, name);
// We provide user information elsewhere if any clients had their debug level set.
// MainConsole.Instance.OutputFormat("Debug packet level set to {0}", newDebug);
}
@ -912,63 +904,30 @@ namespace OpenSim
break;
case "http":
if (args.Length == 3)
{
int newDebug;
if (int.TryParse(args[2], out newDebug))
{
MainServer.Instance.DebugLevel = newDebug;
MainConsole.Instance.OutputFormat("Debug http level set to {0}", newDebug);
break;
}
}
MainConsole.Instance.Output("Usage: debug http 0..2");
break;
case "scene":
if (args.Length == 5)
if (args.Length == 4)
{
if (m_sceneManager.CurrentScene == null)
if (SceneManager.CurrentScene == null)
{
MainConsole.Instance.Output("Please use 'change region <regioname>' first");
}
else
{
bool scriptingOn = !Convert.ToBoolean(args[2]);
bool collisionsOn = !Convert.ToBoolean(args[3]);
bool physicsOn = !Convert.ToBoolean(args[4]);
m_sceneManager.CurrentScene.SetSceneCoreDebug(scriptingOn, collisionsOn, physicsOn);
string key = args[2];
string value = args[3];
SceneManager.CurrentScene.SetSceneCoreDebug(
new Dictionary<string, string>() { { key, value } });
MainConsole.Instance.Output(
String.Format(
"Set debug scene scripting = {0}, collisions = {1}, physics = {2}",
!scriptingOn, !collisionsOn, !physicsOn));
MainConsole.Instance.OutputFormat("Set debug scene {0} = {1}", key, value);
}
}
else
{
MainConsole.Instance.Output("Usage: debug scene <scripting> <collisions> <physics> (where inside <> is true/false)");
MainConsole.Instance.Output("Usage: debug scene scripting|collisions|physics|teleport true|false");
}
break;
case "teleport":
foreach(Scene s in m_sceneManager.Scenes)
{
if (s.DEBUG)
{
s.DEBUG = false;
MainConsole.Instance.Output("Teleport debugging is disabled!");
}
else{
s.DEBUG = true;
MainConsole.Instance.Output("Teleport debugging is enabled!");
}
}
break;
default:
MainConsole.Instance.Output("Unknown debug command");
break;
@ -995,11 +954,10 @@ namespace OpenSim
IList agents;
if (showParams.Length > 1 && showParams[1] == "full")
{
agents = m_sceneManager.GetCurrentScenePresences();
}
else
agents = SceneManager.GetCurrentScenePresences();
} else
{
agents = m_sceneManager.GetCurrentSceneAvatars();
agents = SceneManager.GetCurrentSceneAvatars();
}
MainConsole.Instance.Output(String.Format("\nAgents connected: {0}\n", agents.Count));
@ -1037,63 +995,11 @@ namespace OpenSim
break;
case "connections":
System.Text.StringBuilder connections = new System.Text.StringBuilder("Connections:\n");
m_sceneManager.ForEachScene(
delegate(Scene scene)
{
scene.ForEachClient(
delegate(IClientAPI client)
{
connections.AppendFormat("{0}: {1} ({2}) from {3} on circuit {4}\n",
scene.RegionInfo.RegionName, client.Name, client.AgentId, client.RemoteEndPoint, client.CircuitCode);
}
);
}
);
MainConsole.Instance.Output(connections.ToString());
HandleShowConnections();
break;
case "circuits":
System.Text.StringBuilder acd = new System.Text.StringBuilder("Agent Circuits:\n");
m_sceneManager.ForEachScene(
delegate(Scene scene)
{
//this.HttpServer.
acd.AppendFormat("{0}:\n", scene.RegionInfo.RegionName);
foreach (AgentCircuitData aCircuit in scene.AuthenticateHandler.GetAgentCircuits().Values)
acd.AppendFormat("\t{0} {1} ({2})\n", aCircuit.firstname, aCircuit.lastname, (aCircuit.child ? "Child" : "Root"));
}
);
MainConsole.Instance.Output(acd.ToString());
break;
case "http-handlers":
System.Text.StringBuilder handlers = new System.Text.StringBuilder("Registered HTTP Handlers:\n");
handlers.AppendFormat("* XMLRPC:\n");
foreach (String s in HttpServer.GetXmlRpcHandlerKeys())
handlers.AppendFormat("\t{0}\n", s);
handlers.AppendFormat("* HTTP:\n");
List<String> poll = HttpServer.GetPollServiceHandlerKeys();
foreach (String s in HttpServer.GetHTTPHandlerKeys())
handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty));
handlers.AppendFormat("* Agent:\n");
foreach (String s in HttpServer.GetAgentHandlerKeys())
handlers.AppendFormat("\t{0}\n", s);
handlers.AppendFormat("* LLSD:\n");
foreach (String s in HttpServer.GetLLSDHandlerKeys())
handlers.AppendFormat("\t{0}\n", s);
handlers.AppendFormat("* StreamHandlers ({0}):\n", HttpServer.GetStreamHandlerKeys().Count);
foreach (String s in HttpServer.GetStreamHandlerKeys())
handlers.AppendFormat("\t{0}\n", s);
MainConsole.Instance.Output(handlers.ToString());
HandleShowCircuits();
break;
case "modules":
@ -1103,24 +1009,37 @@ namespace OpenSim
MainConsole.Instance.Output("Shared Module: " + module.Name);
}
m_sceneManager.ForEachScene(
delegate(Scene scene)
SceneManager.ForEachScene(
delegate(Scene scene) {
m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:");
foreach (IRegionModule module in scene.Modules.Values)
{
m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:");
foreach (IRegionModule module in scene.Modules.Values)
if (!module.IsSharedModule)
{
if (!module.IsSharedModule)
{
m_log.Error("Region Module: " + module.Name);
}
m_log.Error("Region Module: " + module.Name);
}
});
}
}
);
SceneManager.ForEachScene(
delegate(Scene scene) {
MainConsole.Instance.Output("Loaded new region modules in" + scene.RegionInfo.RegionName + " are:");
foreach (IRegionModuleBase module in scene.RegionModules.Values)
{
Type type = module.GetType().GetInterface("ISharedRegionModule");
string module_type = type != null ? "Shared" : "Non-Shared";
MainConsole.Instance.OutputFormat("New Region Module ({0}): {1}", module_type, module.Name);
}
}
);
MainConsole.Instance.Output("");
break;
case "regions":
m_sceneManager.ForEachScene(
SceneManager.ForEachScene(
delegate(Scene scene)
{
MainConsole.Instance.Output(String.Format(
@ -1134,7 +1053,7 @@ namespace OpenSim
break;
case "ratings":
m_sceneManager.ForEachScene(
SceneManager.ForEachScene(
delegate(Scene scene)
{
string rating = "";
@ -1159,6 +1078,53 @@ namespace OpenSim
}
}
private void HandleShowCircuits()
{
ConsoleDisplayTable cdt = new ConsoleDisplayTable();
cdt.AddColumn("Region", 20);
cdt.AddColumn("Avatar name", 24);
cdt.AddColumn("Type", 5);
cdt.AddColumn("Code", 10);
cdt.AddColumn("IP", 16);
cdt.AddColumn("Viewer Name", 24);
SceneManager.ForEachScene(
s =>
{
foreach (AgentCircuitData aCircuit in s.AuthenticateHandler.GetAgentCircuits().Values)
cdt.AddRow(
s.Name,
aCircuit.Name,
aCircuit.child ? "child" : "root",
aCircuit.circuitcode.ToString(),
aCircuit.IPAddress.ToString(),
aCircuit.Viewer);
});
MainConsole.Instance.Output(cdt.ToString());
}
private void HandleShowConnections()
{
ConsoleDisplayTable cdt = new ConsoleDisplayTable();
cdt.AddColumn("Region", 20);
cdt.AddColumn("Avatar name", 24);
cdt.AddColumn("Circuit code", 12);
cdt.AddColumn("Endpoint", 23);
cdt.AddColumn("Active?", 7);
SceneManager.ForEachScene(
s => s.ForEachClient(
c => cdt.AddRow(
s.Name,
c.Name,
c.CircuitCode.ToString(),
c.RemoteEndPoint.ToString(),
c.IsActive.ToString())));
MainConsole.Instance.Output(cdt.ToString());
}
/// <summary>
/// Use XML2 format to serialize data to a file
/// </summary>
@ -1168,11 +1134,11 @@ namespace OpenSim
{
if (cmdparams.Length > 5)
{
m_sceneManager.SaveNamedPrimsToXml2(cmdparams[3], cmdparams[4]);
SceneManager.SaveNamedPrimsToXml2(cmdparams[3], cmdparams[4]);
}
else
{
m_sceneManager.SaveNamedPrimsToXml2("Primitive", DEFAULT_PRIM_BACKUP_FILENAME);
SceneManager.SaveNamedPrimsToXml2("Primitive", DEFAULT_PRIM_BACKUP_FILENAME);
}
}
@ -1187,11 +1153,11 @@ namespace OpenSim
if (cmdparams.Length > 0)
{
m_sceneManager.SaveCurrentSceneToXml(cmdparams[2]);
SceneManager.SaveCurrentSceneToXml(cmdparams[2]);
}
else
{
m_sceneManager.SaveCurrentSceneToXml(DEFAULT_PRIM_BACKUP_FILENAME);
SceneManager.SaveCurrentSceneToXml(DEFAULT_PRIM_BACKUP_FILENAME);
}
}
@ -1228,13 +1194,13 @@ namespace OpenSim
MainConsole.Instance.Output(String.Format("loadOffsets <X,Y,Z> = <{0},{1},{2}>",loadOffset.X,loadOffset.Y,loadOffset.Z));
}
}
m_sceneManager.LoadCurrentSceneFromXml(cmdparams[2], generateNewIDS, loadOffset);
SceneManager.LoadCurrentSceneFromXml(cmdparams[2], generateNewIDS, loadOffset);
}
else
{
try
{
m_sceneManager.LoadCurrentSceneFromXml(DEFAULT_PRIM_BACKUP_FILENAME, false, loadOffset);
SceneManager.LoadCurrentSceneFromXml(DEFAULT_PRIM_BACKUP_FILENAME, false, loadOffset);
}
catch (FileNotFoundException)
{
@ -1251,11 +1217,11 @@ namespace OpenSim
{
if (cmdparams.Length > 2)
{
m_sceneManager.SaveCurrentSceneToXml2(cmdparams[2]);
SceneManager.SaveCurrentSceneToXml2(cmdparams[2]);
}
else
{
m_sceneManager.SaveCurrentSceneToXml2(DEFAULT_PRIM_BACKUP_FILENAME);
SceneManager.SaveCurrentSceneToXml2(DEFAULT_PRIM_BACKUP_FILENAME);
}
}
@ -1270,7 +1236,7 @@ namespace OpenSim
{
try
{
m_sceneManager.LoadCurrentSceneFromXml2(cmdparams[2]);
SceneManager.LoadCurrentSceneFromXml2(cmdparams[2]);
}
catch (FileNotFoundException)
{
@ -1281,7 +1247,7 @@ namespace OpenSim
{
try
{
m_sceneManager.LoadCurrentSceneFromXml2(DEFAULT_PRIM_BACKUP_FILENAME);
SceneManager.LoadCurrentSceneFromXml2(DEFAULT_PRIM_BACKUP_FILENAME);
}
catch (FileNotFoundException)
{
@ -1298,7 +1264,7 @@ namespace OpenSim
{
try
{
m_sceneManager.LoadArchiveToCurrentScene(cmdparams);
SceneManager.LoadArchiveToCurrentScene(cmdparams);
}
catch (Exception e)
{
@ -1312,7 +1278,7 @@ namespace OpenSim
/// <param name="cmdparams"></param>
protected void SaveOar(string module, string[] cmdparams)
{
m_sceneManager.SaveCurrentSceneToArchive(cmdparams);
SceneManager.SaveCurrentSceneToArchive(cmdparams);
}
private static string CombineParams(string[] commandParams, int pos)
@ -1344,7 +1310,7 @@ namespace OpenSim
return;
}
m_sceneManager.ForEachScene(
SceneManager.ForEachScene(
delegate(Scene scene)
{
SceneObjectPart part = scene.GetSceneObjectPart(id);

View File

@ -219,7 +219,7 @@ namespace OpenSim
base.StartupSpecific();
m_stats = StatsManager.StartCollectingSimExtraStats();
m_stats = StatsManager.SimExtraStats;
// Create a ModuleLoader instance
m_moduleLoader = new ModuleLoader(m_config.Source);
@ -242,15 +242,18 @@ namespace OpenSim
foreach (string topic in topics)
{
m_console.Commands.AddCommand("plugin", false, "help " + topic,
"help " + topic,
string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1);
// This is a hack to allow the user to enter the help command in upper or lowercase. This will go
// away at some point.
m_console.Commands.AddCommand(capitalizedTopic, false, "help " + topic,
"help " + capitalizedTopic,
"Get help on plugin command '" + topic + "'",
HandleCommanderHelp);
m_console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic,
"help " + capitalizedTopic,
"Get help on plugin command '" + topic + "'",
HandleCommanderHelp);
m_console.Commands.AddCommand("plugin", false, topic,
topic,
"Execute subcommand for plugin '" + topic + "'",
null);
ICommander commander = null;
@ -267,7 +270,7 @@ namespace OpenSim
foreach (string command in commander.Commands.Keys)
{
m_console.Commands.AddCommand(topic, false,
m_console.Commands.AddCommand(capitalizedTopic, false,
topic + " " + command,
topic + " " + commander.Commands[command].ShortHelp(),
String.Empty, HandleCommanderCommand);
@ -278,7 +281,7 @@ namespace OpenSim
private void HandleCommanderCommand(string module, string[] cmd)
{
m_sceneManager.SendCommandToPluginModules(cmd);
SceneManager.SendCommandToPluginModules(cmd);
}
private void HandleCommanderHelp(string module, string[] cmd)
@ -286,7 +289,7 @@ namespace OpenSim
// Only safe for the interactive console, since it won't
// let us come here unless both scene and commander exist
//
ICommander moduleCommander = SceneManager.CurrentOrFirstScene.GetCommander(cmd[1]);
ICommander moduleCommander = SceneManager.CurrentOrFirstScene.GetCommander(cmd[1].ToLower());
if (moduleCommander != null)
m_console.Output(moduleCommander.Help);
}
@ -296,7 +299,10 @@ namespace OpenSim
// Called from base.StartUp()
m_httpServerPort = m_networkServersInfo.HttpListenerPort;
m_sceneManager.OnRestartSim += handleRestartRegion;
SceneManager.OnRestartSim += handleRestartRegion;
// Only start the memory watchdog once all regions are ready
SceneManager.OnRegionsReadyStatusChange += sm => MemoryWatchdog.Enabled = sm.AllRegionsReady;
}
/// <summary>
@ -381,7 +387,7 @@ namespace OpenSim
scene.LoadPrimsFromStorage(regionInfo.originRegionID);
// TODO : Try setting resource for region xstats here on scene
MainServer.Instance.AddStreamHandler(new Region.Framework.Scenes.RegionStatsHandler(regionInfo));
MainServer.Instance.AddStreamHandler(new RegionStatsHandler(regionInfo));
scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID);
scene.EventManager.TriggerParcelPrimCountUpdate();
@ -405,7 +411,7 @@ namespace OpenSim
// scripting engines.
scene.CreateScriptInstances();
m_sceneManager.Add(scene);
SceneManager.Add(scene);
if (m_autoCreateClientStack)
{
@ -424,8 +430,7 @@ namespace OpenSim
mscene = scene;
scene.StartTimer();
scene.Start();
scene.StartScripts();
return clientServer;
@ -512,14 +517,14 @@ namespace OpenSim
{
// only need to check this if we are not at the
// root level
if ((m_sceneManager.CurrentScene != null) &&
(m_sceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID))
if ((SceneManager.CurrentScene != null) &&
(SceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID))
{
m_sceneManager.TrySetCurrentScene("..");
SceneManager.TrySetCurrentScene("..");
}
scene.DeleteAllSceneObjects();
m_sceneManager.CloseScene(scene);
SceneManager.CloseScene(scene);
ShutdownClientServer(scene.RegionInfo);
if (!cleanup)
@ -561,7 +566,7 @@ namespace OpenSim
public void RemoveRegion(string name, bool cleanUp)
{
Scene target;
if (m_sceneManager.TryGetScene(name, out target))
if (SceneManager.TryGetScene(name, out target))
RemoveRegion(target, cleanUp);
}
@ -574,13 +579,13 @@ namespace OpenSim
{
// only need to check this if we are not at the
// root level
if ((m_sceneManager.CurrentScene != null) &&
(m_sceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID))
if ((SceneManager.CurrentScene != null) &&
(SceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID))
{
m_sceneManager.TrySetCurrentScene("..");
SceneManager.TrySetCurrentScene("..");
}
m_sceneManager.CloseScene(scene);
SceneManager.CloseScene(scene);
ShutdownClientServer(scene.RegionInfo);
}
@ -592,7 +597,7 @@ namespace OpenSim
public void CloseRegion(string name)
{
Scene target;
if (m_sceneManager.TryGetScene(name, out target))
if (SceneManager.TryGetScene(name, out target))
CloseRegion(target);
}
@ -724,6 +729,9 @@ namespace OpenSim
return Util.UTF8.GetBytes("OK");
}
public string Name { get { return "SimStatus"; } }
public string Description { get { return "Simulator Status"; } }
public string ContentType
{
get { return "text/plain"; }
@ -749,6 +757,9 @@ namespace OpenSim
OpenSimBase m_opensim;
string osXStatsURI = String.Empty;
public string Name { get { return "XSimStatus"; } }
public string Description { get { return "Simulator XStatus"; } }
public XSimStatusHandler(OpenSimBase sim)
{
m_opensim = sim;
@ -789,6 +800,9 @@ namespace OpenSim
OpenSimBase m_opensim;
string osUXStatsURI = String.Empty;
public string Name { get { return "UXSimStatus"; } }
public string Description { get { return "Simulator UXStatus"; } }
public UXSimStatusHandler(OpenSimBase sim)
{
m_opensim = sim;
@ -839,7 +853,7 @@ namespace OpenSim
try
{
m_sceneManager.Close();
SceneManager.Close();
}
catch (Exception e)
{
@ -864,7 +878,7 @@ namespace OpenSim
/// <param name="usernum">The first out parameter describing the number of all the avatars in the Region server</param>
public void GetAvatarNumber(out int usernum)
{
usernum = m_sceneManager.GetCurrentSceneAvatars().Count;
usernum = SceneManager.GetCurrentSceneAvatars().Count;
}
/// <summary>
@ -873,7 +887,7 @@ namespace OpenSim
/// <param name="regionnum">The first out parameter describing the number of regions</param>
public void GetRegionNumber(out int regionnum)
{
regionnum = m_sceneManager.Scenes.Count;
regionnum = SceneManager.Scenes.Count;
}
/// <summary>

View File

@ -151,7 +151,9 @@ namespace OpenSim.Region.ClientStack.Linden
try
{
// the root of all evil
m_HostCapsObj.RegisterHandler("SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest));
m_HostCapsObj.RegisterHandler(
"SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null));
m_log.DebugFormat(
"[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID);
@ -159,7 +161,10 @@ namespace OpenSim.Region.ClientStack.Linden
// new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST",
// capsBase + m_mapLayerPath,
// GetMapLayer);
IRequestHandler req = new RestStreamHandler("POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory);
IRequestHandler req
= new RestStreamHandler(
"POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory, "UpdateScript", null);
m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req);
m_HostCapsObj.RegisterHandler("UpdateScriptTask", req);
}
@ -174,14 +179,27 @@ namespace OpenSim.Region.ClientStack.Linden
try
{
// I don't think this one works...
m_HostCapsObj.RegisterHandler("NewFileAgentInventory", new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>("POST",
capsBase + m_newInventory,
NewAgentInventoryRequest));
IRequestHandler req = new RestStreamHandler("POST", capsBase + m_notecardUpdatePath, NoteCardAgentInventory);
m_HostCapsObj.RegisterHandler(
"NewFileAgentInventory",
new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>(
"POST",
capsBase + m_newInventory,
NewAgentInventoryRequest,
"NewFileAgentInventory",
null));
IRequestHandler req
= new RestStreamHandler(
"POST", capsBase + m_notecardUpdatePath, NoteCardAgentInventory, "Update*", null);
m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req);
m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req);
m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req);
m_HostCapsObj.RegisterHandler("CopyInventoryFromNotecard", new RestStreamHandler("POST", capsBase + m_copyFromNotecardPath, CopyInventoryFromNotecard));
m_HostCapsObj.RegisterHandler(
"CopyInventoryFromNotecard",
new RestStreamHandler(
"POST", capsBase + m_copyFromNotecardPath, CopyInventoryFromNotecard, "CopyInventoryFromNotecard", null));
// As of RC 1.22.9 of the Linden client this is
// supported
@ -231,7 +249,10 @@ namespace OpenSim.Region.ClientStack.Linden
if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint))
{
m_log.DebugFormat("[CAPS]: Unauthorized CAPS client");
m_log.DebugFormat(
"[CAPS]: Unauthorized CAPS client {0} from {1}",
m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint);
return string.Empty;
}
@ -262,7 +283,7 @@ namespace OpenSim.Region.ClientStack.Linden
{
try
{
m_log.Debug("[CAPS]: ScriptTaskInventory Request in region: " + m_regionName);
// m_log.Debug("[CAPS]: ScriptTaskInventory Request in region: " + m_regionName);
//m_log.DebugFormat("[CAPS]: request: {0}, path: {1}, param: {2}", request, path, param);
Hashtable hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
@ -282,7 +303,9 @@ namespace OpenSim.Region.ClientStack.Linden
m_dumpAssetsToFile);
uploader.OnUpLoad += TaskScriptUpdated;
m_HostCapsObj.HttpListener.AddStreamHandler(new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps));
m_HostCapsObj.HttpListener.AddStreamHandler(
new BinaryStreamHandler(
"POST", capsBase + uploaderPath, uploader.uploaderCaps, "TaskInventoryScriptUpdater", null));
string protocol = "http://";
@ -393,8 +416,14 @@ namespace OpenSim.Region.ClientStack.Linden
AssetUploader uploader =
new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile);
m_HostCapsObj.HttpListener.AddStreamHandler(
new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps));
new BinaryStreamHandler(
"POST",
capsBase + uploaderPath,
uploader.uploaderCaps,
"NewAgentInventoryRequest",
m_HostCapsObj.AgentID.ToString()));
string protocol = "http://";
@ -710,7 +739,8 @@ namespace OpenSim.Region.ClientStack.Linden
uploader.OnUpLoad += ItemUpdated;
m_HostCapsObj.HttpListener.AddStreamHandler(
new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps));
new BinaryStreamHandler(
"POST", capsBase + uploaderPath, uploader.uploaderCaps, "NoteCardAgentInventory", null));
string protocol = "http://";

View File

@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden
//scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack);
scene.EventManager.OnNewClient += OnNewClient;
// scene.EventManager.OnNewClient += OnNewClient;
// TODO: Leaving these open, or closing them when we
// become a child is incorrect. It messes up TP in a big
@ -102,17 +102,19 @@ namespace OpenSim.Region.ClientStack.Linden
// circuit is there.
scene.EventManager.OnClientClosed += ClientClosed;
scene.EventManager.OnMakeChildAgent += MakeChildAgent;
scene.EventManager.OnRegisterCaps += OnRegisterCaps;
MainConsole.Instance.Commands.AddCommand(
"event queue",
"Debug",
false,
"debug eq",
"debug eq [0|1]",
"Turn on event queue debugging",
"debug eq 1 will turn on event queue debugging. This will log all outgoing event queue messages to clients.\n"
+ "debug eq 0 will turn off event queue debugging.",
"debug eq [0|1|2]",
"Turn on event queue debugging"
+ "<= 0 - turns off all event queue logging"
+ ">= 1 - turns on outgoing event logging"
+ ">= 2 - turns on poll notification",
HandleDebugEq);
}
else
@ -225,29 +227,19 @@ namespace OpenSim.Region.ClientStack.Linden
#endregion
private void OnNewClient(IClientAPI client)
private void ClientClosed(UUID agentID, Scene scene)
{
//client.OnLogout += ClientClosed;
}
// private void ClientClosed(IClientAPI client)
// {
// ClientClosed(client.AgentId);
// }
private void ClientClosed(UUID AgentID, Scene scene)
{
// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", AgentID, m_scene.RegionInfo.RegionName);
// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
int count = 0;
while (queues.ContainsKey(AgentID) && queues[AgentID].Count > 0 && count++ < 5)
while (queues.ContainsKey(agentID) && queues[agentID].Count > 0 && count++ < 5)
{
Thread.Sleep(1000);
}
lock (queues)
{
queues.Remove(AgentID);
queues.Remove(agentID);
}
List<UUID> removeitems = new List<UUID>();
@ -256,7 +248,7 @@ namespace OpenSim.Region.ClientStack.Linden
foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys)
{
// m_log.DebugFormat("[EVENTQUEUE]: Found key {0} in m_AvatarQueueUUIDMapping while looking for {1}", ky, AgentID);
if (ky == AgentID)
if (ky == agentID)
{
removeitems.Add(ky);
}
@ -267,7 +259,12 @@ namespace OpenSim.Region.ClientStack.Linden
UUID eventQueueGetUuid = m_AvatarQueueUUIDMapping[ky];
m_AvatarQueueUUIDMapping.Remove(ky);
MainServer.Instance.RemovePollServiceHTTPHandler("","/CAPS/EQG/" + eventQueueGetUuid.ToString() + "/");
string eqgPath = GenerateEqgCapPath(eventQueueGetUuid);
MainServer.Instance.RemovePollServiceHTTPHandler("", eqgPath);
// m_log.DebugFormat(
// "[EVENT QUEUE GET MODULE]: Removed EQG handler {0} for {1} in {2}",
// eqgPath, agentID, m_scene.RegionInfo.RegionName);
}
}
@ -281,7 +278,7 @@ namespace OpenSim.Region.ClientStack.Linden
{
searchval = m_QueueUUIDAvatarMapping[ky];
if (searchval == AgentID)
if (searchval == agentID)
{
removeitems.Add(ky);
}
@ -305,6 +302,15 @@ namespace OpenSim.Region.ClientStack.Linden
//}
}
/// <summary>
/// Generate an Event Queue Get handler path for the given eqg uuid.
/// </summary>
/// <param name='eqgUuid'></param>
private string GenerateEqgCapPath(UUID eqgUuid)
{
return string.Format("/CAPS/EQG/{0}/", eqgUuid);
}
public void OnRegisterCaps(UUID agentID, Caps caps)
{
// Register an event queue for the client
@ -316,8 +322,7 @@ namespace OpenSim.Region.ClientStack.Linden
// Let's instantiate a Queue for this agent right now
TryGetQueue(agentID);
string capsBase = "/CAPS/EQG/";
UUID EventQueueGetUUID = UUID.Zero;
UUID eventQueueGetUUID;
lock (m_AvatarQueueUUIDMapping)
{
@ -325,44 +330,50 @@ namespace OpenSim.Region.ClientStack.Linden
if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
{
//m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!");
EventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
}
else
{
EventQueueGetUUID = UUID.Random();
eventQueueGetUUID = UUID.Random();
//m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!");
}
}
lock (m_QueueUUIDAvatarMapping)
{
if (!m_QueueUUIDAvatarMapping.ContainsKey(EventQueueGetUUID))
m_QueueUUIDAvatarMapping.Add(EventQueueGetUUID, agentID);
if (!m_QueueUUIDAvatarMapping.ContainsKey(eventQueueGetUUID))
m_QueueUUIDAvatarMapping.Add(eventQueueGetUUID, agentID);
}
lock (m_AvatarQueueUUIDMapping)
{
if (!m_AvatarQueueUUIDMapping.ContainsKey(agentID))
m_AvatarQueueUUIDMapping.Add(agentID, EventQueueGetUUID);
m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
}
string eventQueueGetPath = GenerateEqgCapPath(eventQueueGetUUID);
// Register this as a caps handler
// FIXME: Confusingly, we need to register separate as a capability so that the client is told about
// EventQueueGet when it receive capability information, but then we replace the rest handler immediately
// afterwards with the poll service. So for now, we'll pass a null instead to simplify code reading, but
// really it should be possible to directly register the poll handler as a capability.
caps.RegisterHandler("EventQueueGet",
new RestHTTPHandler("POST", capsBase + EventQueueGetUUID.ToString() + "/", null));
caps.RegisterHandler("EventQueueGet", new RestHTTPHandler("POST", eventQueueGetPath, null));
// delegate(Hashtable m_dhttpMethod)
// {
// return ProcessQueue(m_dhttpMethod, agentID, caps);
// }));
// This will persist this beyond the expiry of the caps handlers
// TODO: Add EventQueueGet name/description for diagnostics
MainServer.Instance.AddPollServiceHTTPHandler(
capsBase + EventQueueGetUUID.ToString() + "/",
eventQueueGetPath,
new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID));
// m_log.DebugFormat(
// "[EVENT QUEUE GET MODULE]: Registered EQG handler {0} for {1} in {2}",
// eventQueueGetPath, agentID, m_scene.RegionInfo.RegionName);
Random rnd = new Random(Environment.TickCount);
lock (m_ids)
{
@ -384,9 +395,25 @@ namespace OpenSim.Region.ClientStack.Linden
return false;
}
/// <summary>
/// Logs a debug line for an outbound event queue message if appropriate.
/// </summary>
/// <param name='element'>Element containing message</param>
private void LogOutboundDebugMessage(OSD element, UUID agentId)
{
if (element is OSDMap)
{
OSDMap ev = (OSDMap)element;
m_log.DebugFormat(
"Eq OUT {0,-30} to {1,-20} {2,-20}",
ev["message"], m_scene.GetScenePresence(agentId).Name, m_scene.RegionInfo.RegionName);
}
}
public Hashtable GetEvents(UUID requestID, UUID pAgentId, string request)
{
// m_log.DebugFormat("[EVENT QUEUE GET MODULE]: Invoked GetEvents() for {0}", pAgentId);
if (DebugLevel >= 2)
m_log.DebugFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName);
Queue<OSD> queue = TryGetQueue(pAgentId);
OSD element;
@ -410,13 +437,8 @@ namespace OpenSim.Region.ClientStack.Linden
}
else
{
if (DebugLevel > 0 && element is OSDMap)
{
OSDMap ev = (OSDMap)element;
m_log.DebugFormat(
"[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
ev["message"], m_scene.GetScenePresence(pAgentId).Name);
}
if (DebugLevel > 0)
LogOutboundDebugMessage(element, pAgentId);
array.Add(element);
@ -426,13 +448,8 @@ namespace OpenSim.Region.ClientStack.Linden
{
element = queue.Dequeue();
if (DebugLevel > 0 && element is OSDMap)
{
OSDMap ev = (OSDMap)element;
m_log.DebugFormat(
"[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
ev["message"], m_scene.GetScenePresence(pAgentId).Name);
}
if (DebugLevel > 0)
LogOutboundDebugMessage(element, pAgentId);
array.Add(element);
thisID++;

View File

@ -51,7 +51,16 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
[SetUp]
public void SetUp()
{
MainServer.Instance = new BaseHttpServer(9999, false, 9998, "");
uint port = 9999;
uint sslPort = 9998;
// This is an unfortunate bit of clean up we have to do because MainServer manages things through static
// variables and the VM is not restarted between tests.
MainServer.RemoveHttpServer(port);
BaseHttpServer server = new BaseHttpServer(port, false, sslPort, "");
MainServer.AddHttpServer(server);
MainServer.Instance = server;
IConfigSource config = new IniConfigSource();
config.AddConfig("Startup");
@ -60,7 +69,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
CapabilitiesModule capsModule = new CapabilitiesModule();
EventQueueGetModule eqgModule = new EventQueueGetModule();
m_scene = SceneHelpers.SetupScene();
m_scene = new SceneHelpers().SetupScene();
SceneHelpers.SetupSceneModules(m_scene, config, capsModule, eqgModule);
}
@ -85,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
UUID spId = TestHelpers.ParseTail(0x1);
SceneHelpers.AddScenePresence(m_scene, spId);
m_scene.IncomingCloseAgent(spId);
m_scene.IncomingCloseAgent(spId, false);
// TODO: Add more assertions for the other aspects of event queues
Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0));

View File

@ -132,7 +132,8 @@ namespace OpenSim.Region.ClientStack.Linden
capUrl = "/CAPS/" + UUID.Random();
IRequestHandler reqHandler
= new RestStreamHandler("POST", capUrl, m_fetchHandler.FetchInventoryRequest);
= new RestStreamHandler(
"POST", capUrl, m_fetchHandler.FetchInventoryRequest, capName, agentID.ToString());
caps.RegisterHandler(capName, reqHandler);
}

View File

@ -120,11 +120,13 @@ namespace OpenSim.Region.ClientStack.Linden
{
// m_log.DebugFormat("[GETMESH]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName);
GetMeshHandler gmeshHandler = new GetMeshHandler(m_AssetService);
IRequestHandler reqHandler = new RestHTTPHandler("GET", "/CAPS/" + UUID.Random(),
delegate(Hashtable m_dhttpMethod)
{
return gmeshHandler.ProcessGetMesh(m_dhttpMethod, UUID.Zero, null);
});
IRequestHandler reqHandler
= new RestHTTPHandler(
"GET",
"/CAPS/" + UUID.Random(),
httpMethod => gmeshHandler.ProcessGetMesh(httpMethod, UUID.Zero, null),
"GetMesh",
agentID.ToString());
caps.RegisterHandler("GetMesh", reqHandler);
}

View File

@ -130,7 +130,9 @@ namespace OpenSim.Region.ClientStack.Linden
if (m_URL == "localhost")
{
// m_log.DebugFormat("[GETTEXTURE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName);
caps.RegisterHandler("GetTexture", new GetTextureHandler("/CAPS/" + capID + "/", m_assetService));
caps.RegisterHandler(
"GetTexture",
new GetTextureHandler("/CAPS/" + capID + "/", m_assetService, "GetTexture", agentID.ToString()));
}
else
{

View File

@ -117,7 +117,9 @@ namespace OpenSim.Region.ClientStack.Linden
public void RegisterCaps(UUID agentID, Caps caps)
{
IRequestHandler reqHandler = new RestHTTPHandler("GET", "/CAPS/" + UUID.Random(), MeshUploadFlag);
IRequestHandler reqHandler
= new RestHTTPHandler("GET", "/CAPS/" + UUID.Random(), MeshUploadFlag, "MeshUploadFlag", agentID.ToString());
caps.RegisterHandler("MeshUploadFlag", reqHandler);
m_agentID = agentID;
}

View File

@ -56,6 +56,7 @@ namespace OpenSim.Region.ClientStack.Linden
// private IAssetService m_assetService;
private bool m_dumpAssetsToFile = false;
private bool m_enabled = true;
private int m_levelUpload = 0;
#region IRegionModuleBase Members
@ -72,6 +73,7 @@ namespace OpenSim.Region.ClientStack.Linden
return;
m_enabled = meshConfig.GetBoolean("AllowMeshUpload", true);
m_levelUpload = meshConfig.GetInt("LevelUpload", 0);
}
public void AddRegion(Scene pScene)
@ -113,51 +115,66 @@ namespace OpenSim.Region.ClientStack.Linden
UUID capID = UUID.Random();
// m_log.Debug("[NEW FILE AGENT INVENTORY VARIABLE PRICE]: /CAPS/" + capID);
caps.RegisterHandler("NewFileAgentInventoryVariablePrice",
new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDNewFileAngentInventoryVariablePriceReplyResponse>("POST",
"/CAPS/" + capID.ToString(),
delegate(LLSDAssetUploadRequest req)
{
return NewAgentInventoryRequest(req,agentID);
}));
caps.RegisterHandler(
"NewFileAgentInventoryVariablePrice",
new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDNewFileAngentInventoryVariablePriceReplyResponse>(
"POST",
"/CAPS/" + capID.ToString(),
req => NewAgentInventoryRequest(req, agentID),
"NewFileAgentInventoryVariablePrice",
agentID.ToString()));
}
#endregion
public LLSDNewFileAngentInventoryVariablePriceReplyResponse NewAgentInventoryRequest(LLSDAssetUploadRequest llsdRequest, UUID agentID)
{
//TODO: The Mesh uploader uploads many types of content. If you're going to implement a Money based limit
// You need to be aware of this and
// you need to be aware of this
//if (llsdRequest.asset_type == "texture" ||
// llsdRequest.asset_type == "animation" ||
// llsdRequest.asset_type == "sound")
// {
IClientAPI client = null;
// check user level
ScenePresence avatar = null;
IClientAPI client = null;
m_scene.TryGetScenePresence(agentID, out avatar);
IMoneyModule mm = m_scene.RequestModuleInterface<IMoneyModule>();
if (avatar != null)
{
client = avatar.ControllingClient;
if (mm != null)
if (avatar.UserLevel < m_levelUpload)
{
if (m_scene.TryGetClient(agentID, out client))
{
if (!mm.UploadCovered(client.AgentId, mm.UploadCharge))
{
if (client != null)
client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false);
if (client != null)
client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false);
LLSDNewFileAngentInventoryVariablePriceReplyResponse errorResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
errorResponse.rsvp = "";
errorResponse.state = "error";
return errorResponse;
}
}
LLSDNewFileAngentInventoryVariablePriceReplyResponse errorResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
errorResponse.rsvp = "";
errorResponse.state = "error";
return errorResponse;
}
}
// check funds
IMoneyModule mm = m_scene.RequestModuleInterface<IMoneyModule>();
if (mm != null)
{
if (!mm.UploadCovered(agentID, mm.UploadCharge))
{
if (client != null)
client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false);
LLSDNewFileAngentInventoryVariablePriceReplyResponse errorResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
errorResponse.rsvp = "";
errorResponse.state = "error";
return errorResponse;
}
}
// }
string assetName = llsdRequest.name;
@ -171,8 +188,14 @@ namespace OpenSim.Region.ClientStack.Linden
AssetUploader uploader =
new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
llsdRequest.asset_type, capsBase + uploaderPath, MainServer.Instance, m_dumpAssetsToFile);
MainServer.Instance.AddStreamHandler(
new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps));
new BinaryStreamHandler(
"POST",
capsBase + uploaderPath,
uploader.uploaderCaps,
"NewFileAgentInventoryVariablePrice",
agentID.ToString()));
string protocol = "http://";
@ -185,7 +208,6 @@ namespace OpenSim.Region.ClientStack.Linden
LLSDNewFileAngentInventoryVariablePriceReplyResponse uploadResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
uploadResponse.rsvp = uploaderURL;
uploadResponse.state = "upload";
uploadResponse.resource_cost = 0;
@ -202,6 +224,7 @@ namespace OpenSim.Region.ClientStack.Linden
pinventoryItem, pparentFolder, pdata, pinventoryType,
passetType,agentID);
};
return uploadResponse;
}

View File

@ -66,12 +66,14 @@ namespace OpenSim.Region.ClientStack.Linden
// m_log.InfoFormat("[OBJECTADD]: {0}", "/CAPS/OA/" + capuuid + "/");
caps.RegisterHandler("ObjectAdd",
new RestHTTPHandler("POST", "/CAPS/OA/" + capuuid + "/",
delegate(Hashtable m_dhttpMethod)
{
return ProcessAdd(m_dhttpMethod, agentID, caps);
}));
caps.RegisterHandler(
"ObjectAdd",
new RestHTTPHandler(
"POST",
"/CAPS/OA/" + capuuid + "/",
httpMethod => ProcessAdd(httpMethod, agentID, caps),
"ObjectAdd",
agentID.ToString()));;
}
public Hashtable ProcessAdd(Hashtable request, UUID AgentId, Caps cap)

View File

@ -106,12 +106,15 @@ namespace OpenSim.Region.ClientStack.Linden
UUID capID = UUID.Random();
// m_log.Debug("[UPLOAD OBJECT ASSET MODULE]: /CAPS/" + capID);
caps.RegisterHandler("UploadObjectAsset",
new RestHTTPHandler("POST", "/CAPS/OA/" + capID + "/",
delegate(Hashtable m_dhttpMethod)
{
return ProcessAdd(m_dhttpMethod, agentID, caps);
}));
caps.RegisterHandler(
"UploadObjectAsset",
new RestHTTPHandler(
"POST",
"/CAPS/OA/" + capID + "/",
httpMethod => ProcessAdd(httpMethod, agentID, caps),
"UploadObjectAsset",
agentID.ToString()));
/*
caps.RegisterHandler("NewFileAgentInventoryVariablePrice",
@ -330,7 +333,6 @@ namespace OpenSim.Region.ClientStack.Linden
grp.AbsolutePosition = obj.Position;
prim.RotationOffset = obj.Rotation;
grp.IsAttachment = false;
// Required for linking
grp.RootPart.ClearUpdateSchedule();

View File

@ -154,7 +154,9 @@ namespace OpenSim.Region.ClientStack.Linden
public void RegisterCaps(UUID agentID, Caps caps)
{
IRequestHandler reqHandler
= new RestHTTPHandler("GET", "/CAPS/" + UUID.Random(), HandleSimulatorFeaturesRequest);
= new RestHTTPHandler(
"GET", "/CAPS/" + UUID.Random(),
HandleSimulatorFeaturesRequest, "SimulatorFeatures", agentID.ToString());
caps.RegisterHandler("SimulatorFeatures", reqHandler);
}

View File

@ -106,7 +106,9 @@ namespace OpenSim.Region.ClientStack.Linden
"POST",
"/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath,
new UploadBakedTextureHandler(
caps, m_scene.AssetService, m_persistBakedTextures).UploadBakedTexture));
caps, m_scene.AssetService, m_persistBakedTextures).UploadBakedTexture,
"UploadBakedTexture",
agentID.ToString()));
}
}
}

View File

@ -144,7 +144,12 @@ namespace OpenSim.Region.ClientStack.Linden
capUrl = "/CAPS/" + UUID.Random();
IRequestHandler reqHandler
= new RestStreamHandler("POST", capUrl, m_webFetchHandler.FetchInventoryDescendentsRequest);
= new RestStreamHandler(
"POST",
capUrl,
m_webFetchHandler.FetchInventoryDescendentsRequest,
"FetchInventoryDescendents2",
agentID.ToString());
caps.RegisterHandler(capName, reqHandler);
}

View File

@ -39,7 +39,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public sealed class IncomingPacket
{
/// <summary>Client this packet came from</summary>
public LLUDPClient Client;
public LLClientView Client;
/// <summary>Packet data that has been received</summary>
public Packet Packet;
@ -48,7 +49,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// </summary>
/// <param name="client">Reference to the client this packet came from</param>
/// <param name="packet">Packet data</param>
public IncomingPacket(LLUDPClient client, Packet packet)
public IncomingPacket(LLClientView client, Packet packet)
{
Client = client;
Packet = packet;

View File

@ -59,7 +59,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Handles new client connections
/// Constructor takes a single Packet and authenticates everything
/// </summary>
public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientIPEndpoint, IStatsCollector
public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientInventory, IStatsCollector
{
/// <value>
/// Debug packet level. See OpenSim.RegisterConsoleCommands() for more details.
@ -348,8 +348,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private int m_animationSequenceNumber = 1;
private bool m_SendLogoutPacketWhenClosing = true;
private AgentUpdateArgs lastarg;
private bool m_IsActive = true;
private bool m_IsLoggingOut = false;
protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@ -358,7 +356,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
protected string m_lastName;
protected Thread m_clientThread;
protected Vector3 m_startpos;
protected EndPoint m_userEndPoint;
protected UUID m_activeGroupID;
protected string m_activeGroupName = String.Empty;
protected ulong m_activeGroupPowers;
@ -385,7 +382,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
set { m_startpos = value; }
}
public UUID AgentId { get { return m_agentId; } }
public ISceneAgent SceneAgent { get; private set; }
public ISceneAgent SceneAgent { get; set; }
public UUID ActiveGroupId { get { return m_activeGroupID; } }
public string ActiveGroupName { get { return m_activeGroupName; } }
public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } }
@ -414,16 +411,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public uint CircuitCode { get { return m_circuitCode; } }
public int MoneyBalance { get { return m_moneyBalance; } }
public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } }
public bool IsActive
{
get { return m_IsActive; }
set { m_IsActive = value; }
}
public bool IsLoggingOut
{
get { return m_IsLoggingOut; }
set { m_IsLoggingOut = value; }
}
/// <summary>
/// As well as it's function in IClientAPI, in LLClientView we are locking on this property in order to
/// prevent race conditions by different threads calling Close().
/// </summary>
public bool IsActive { get; set; }
/// <summary>
/// Used to synchronise threads when client is being closed.
/// </summary>
public Object CloseSyncLock { get; private set; }
public bool IsLoggingOut { get; set; }
public bool DisableFacelights
{
@ -443,14 +443,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <summary>
/// Constructor
/// </summary>
public LLClientView(EndPoint remoteEP, Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo,
public LLClientView(Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo,
UUID agentId, UUID sessionId, uint circuitCode)
{
// DebugPacketLevel = 1;
CloseSyncLock = new Object();
RegisterInterface<IClientIM>(this);
RegisterInterface<IClientInventory>(this);
RegisterInterface<IClientChat>(this);
RegisterInterface<IClientIPEndpoint>(this);
InitDefaultAnimations();
@ -470,7 +472,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_sessionId = sessionId;
m_secureSessionId = sessionInfo.LoginInfo.SecureSession;
m_circuitCode = circuitCode;
m_userEndPoint = remoteEP;
m_firstName = sessionInfo.LoginInfo.First;
m_lastName = sessionInfo.LoginInfo.Last;
m_startpos = sessionInfo.LoginInfo.StartPos;
@ -484,25 +485,48 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_prioritizer = new Prioritizer(m_scene);
RegisterLocalPacketHandlers();
IsActive = true;
}
#region Client Methods
/// <summary>
/// Shut down the client view
/// </summary>
public void Close()
{
Close(false);
}
public void Close(bool force)
{
// We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
// a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
lock (CloseSyncLock)
{
// We still perform a force close inside the sync lock since this is intended to attempt close where
// there is some unidentified connection problem, not where we have issues due to deadlock
if (!IsActive && !force)
return;
IsActive = false;
CloseWithoutChecks();
}
}
/// <summary>
/// Closes down the client view without first checking whether it is active.
/// </summary>
/// <remarks>
/// This exists because LLUDPServer has to set IsActive = false in earlier synchronous code before calling
/// CloseWithoutIsActiveCheck asynchronously.
///
/// Callers must lock ClosingSyncLock before calling.
/// </remarks>
public void CloseWithoutChecks()
{
m_log.DebugFormat(
"[CLIENT]: Close has been called for {0} attached to scene {1}",
Name, m_scene.RegionInfo.RegionName);
// Send the STOP packet
DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
OutPacket(disable, ThrottleOutPacketType.Unknown);
IsActive = false;
// Shutdown the image manager
ImageManager.Close();
@ -698,7 +722,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public virtual void Start()
{
SceneAgent = m_scene.AddNewClient(this, PresenceType.User);
m_scene.AddNewClient(this, PresenceType.User);
RefreshGroupMembership();
}
@ -2725,6 +2749,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
public void SendAssetNotFound(AssetRequestToClient req)
{
TransferInfoPacket Transfer = new TransferInfoPacket();
Transfer.TransferInfo.ChannelType = 2;
Transfer.TransferInfo.Status = -2;
Transfer.TransferInfo.TargetType = 0;
Transfer.TransferInfo.Params = req.Params;
Transfer.TransferInfo.Size = 0;
Transfer.TransferInfo.TransferID = req.TransferRequestID;
Transfer.Header.Zerocoded = true;
OutPacket(Transfer, ThrottleOutPacketType.Asset);
}
public void SendTexture(AssetBase TextureAsset)
{
@ -3563,7 +3600,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
{
if (!IsActive) return; // We don't need to update inactive clients.
// We don't need to update inactive clients.
if (!IsActive)
return;
CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate);
loc.Header.Reliable = false;
@ -3728,8 +3767,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
++updatesThisCall;
#region UpdateFlags to packet type conversion
PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
@ -3786,20 +3823,53 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (!canUseImproved && !canUseCompressed)
{
ObjectUpdatePacket.ObjectDataBlock updateBlock;
if (update.Entity is ScenePresence)
{
objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
objectUpdates.Value.Add(update);
updateBlock = CreateAvatarUpdateBlock((ScenePresence)update.Entity);
}
else
{
objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
objectUpdates.Value.Add(update);
SceneObjectPart part = (SceneObjectPart)update.Entity;
updateBlock = CreatePrimUpdateBlock(part, AgentId);
// If the part has become a private hud since the update was scheduled then we do not
// want to send it to other avatars.
if (part.ParentGroup.IsAttachment
&& part.ParentGroup.HasPrivateAttachmentPoint
&& part.ParentGroup.AttachedAvatar != AgentId)
continue;
// If the part has since been deleted, then drop the update. In the case of attachments,
// this is to avoid spurious updates to other viewers since post-processing of attachments
// has to change the IsAttachment flag for various reasons (which will end up in a pass
// of the test above).
//
// Actual deletions (kills) happen in another method.
if (part.ParentGroup.IsDeleted)
continue;
}
objectUpdateBlocks.Value.Add(updateBlock);
objectUpdates.Value.Add(update);
}
else if (!canUseImproved)
{
compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
SceneObjectPart part = (SceneObjectPart)update.Entity;
ObjectUpdateCompressedPacket.ObjectDataBlock compressedBlock
= CreateCompressedUpdateBlock(part, updateFlags);
// If the part has since been deleted, then drop the update. In the case of attachments,
// this is to avoid spurious updates to other viewers since post-processing of attachments
// has to change the IsAttachment flag for various reasons (which will end up in a pass
// of the test above).
//
// Actual deletions (kills) happen in another method.
if (part.ParentGroup.IsDeleted)
continue;
compressedUpdateBlocks.Value.Add(compressedBlock);
compressedUpdates.Value.Add(update);
}
else
@ -3812,16 +3882,41 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
else
{
ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseUpdateBlock
= CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures));
// Everything else goes here
terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
if (update.Entity is SceneObjectPart)
{
SceneObjectPart part = (SceneObjectPart)update.Entity;
// If the part has become a private hud since the update was scheduled then we do not
// want to send it to other avatars.
if (part.ParentGroup.IsAttachment
&& part.ParentGroup.HasPrivateAttachmentPoint
&& part.ParentGroup.AttachedAvatar != AgentId)
continue;
// If the part has since been deleted, then drop the update. In the case of attachments,
// this is to avoid spurious updates to other viewers since post-processing of attachments
// has to change the IsAttachment flag for various reasons (which will end up in a pass
// of the test above).
//
// Actual deletions (kills) happen in another method.
if (part.ParentGroup.IsDeleted)
continue;
}
terseUpdateBlocks.Value.Add(terseUpdateBlock);
terseUpdates.Value.Add(update);
}
}
++updatesThisCall;
#endregion Block Construction
}
#region Packet Sending
ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
@ -4273,7 +4368,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
block.OwnerID = sop.OwnerID;
block.ItemID = sop.FromUserInventoryItemID;
block.FolderID = UUID.Zero; // sop.FromFolderID ??
block.FolderID = UUID.Zero; // sog.FromFolderID ??
block.FromTaskID = UUID.Zero; // ???
block.InventorySerial = (short)sop.InventorySerial;
@ -4959,7 +5054,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
if (data.ParentGroup.IsAttachment)
{
update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.FromItemID);
update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.ParentGroup.FromItemID);
update.State = (byte)((data.ParentGroup.AttachmentPoint % 16) * 16 + (data.ParentGroup.AttachmentPoint / 16));
}
else
@ -5104,7 +5199,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer);
AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate);
AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply);
AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage, false);
AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage);
AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship);
AddLocalPacketHandler(PacketType.DeclineFriendship, HandlerDeclineFriendship);
AddLocalPacketHandler(PacketType.TerminateFriendship, HandlerTerminateFriendship);
@ -5787,7 +5882,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// My guess is this is the folder to stick the calling card into
List<UUID> callingCardFolders = new List<UUID>();
UUID agentID = afriendpack.AgentData.AgentID;
UUID transactionID = afriendpack.TransactionBlock.TransactionID;
for (int fi = 0; fi < afriendpack.FolderData.Length; fi++)
@ -5798,10 +5892,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
FriendActionDelegate handlerApproveFriendRequest = OnApproveFriendRequest;
if (handlerApproveFriendRequest != null)
{
handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders);
handlerApproveFriendRequest(this, transactionID, callingCardFolders);
}
return true;
return true;
}
private bool HandlerDeclineFriendship(IClientAPI sender, Packet Pack)
@ -5820,7 +5914,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (OnDenyFriendRequest != null)
{
OnDenyFriendRequest(this,
dfriendpack.AgentData.AgentID,
dfriendpack.TransactionBlock.TransactionID,
null);
}
@ -5840,14 +5933,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
#endregion
UUID listOwnerAgentID = tfriendpack.AgentData.AgentID;
UUID exFriendID = tfriendpack.ExBlock.OtherID;
FriendshipTermination TerminateFriendshipHandler = OnTerminateFriendship;
if (TerminateFriendshipHandler != null)
{
TerminateFriendshipHandler(this, listOwnerAgentID, exFriendID);
TerminateFriendshipHandler(this, exFriendID);
return true;
}
return false;
}
@ -11165,12 +11258,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return true;
}
#endregion
GrantUserFriendRights GrantUserRightsHandler = OnGrantUserRights;
if (GrantUserRightsHandler != null)
GrantUserRightsHandler(this,
GrantUserRights.AgentData.AgentID,
GrantUserRights.Rights[0].AgentRelated,
GrantUserRights.Rights[0].RelatedRights);
return true;
}
@ -11683,7 +11777,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (DebugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect))
logPacket = false;
if (DebugPacketLevel <= 50 && packet.Type == PacketType.ImprovedTerseObjectUpdate)
if (DebugPacketLevel <= 50
& (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate))
logPacket = false;
if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily)
@ -11796,7 +11891,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
ClientInfo info = m_udpClient.GetClientInfo();
info.userEP = m_userEndPoint;
info.proxyEP = null;
info.agentcircuit = RequestClientInfo();
@ -11808,11 +11902,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_udpClient.SetClientInfo(info);
}
public EndPoint GetClientEP()
{
return m_userEndPoint;
}
#region Media Parcel Members
public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time)
@ -11893,10 +11982,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return string.Empty;
}
public void KillEndDone()
{
}
#region IClientCore
private readonly Dictionary<Type, object> m_clientInterfaces = new Dictionary<Type, object>();
@ -11937,7 +12022,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
Kick(reason);
Thread.Sleep(1000);
Close();
Disconnect();
}
public void Disconnect()
@ -11984,21 +12069,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
protected void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID)
{
UUID requestID = UUID.Zero;
if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset)
int sourceType = transferRequest.TransferInfo.SourceType;
if (sourceType == (int)SourceType.Asset)
{
requestID = new UUID(transferRequest.TransferInfo.Params, 0);
}
else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem)
else if (sourceType == (int)SourceType.SimInventoryItem)
{
requestID = new UUID(transferRequest.TransferInfo.Params, 80);
}
else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimEstate)
else if (sourceType == (int)SourceType.SimEstate)
{
requestID = taskID;
}
// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
// m_log.DebugFormat(
// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}",
// requestID, taskID, (SourceType)sourceType, Name);
m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
}
@ -12011,14 +12099,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="asset"></param>
protected void AssetReceived(string id, Object sender, AssetBase asset)
{
if (asset == null)
return;
TransferRequestPacket transferRequest = (TransferRequestPacket)sender;
UUID requestID = UUID.Zero;
byte source = (byte)SourceType.Asset;
AssetRequestToClient req = new AssetRequestToClient();
if (asset == null)
{
req.AssetInf = null;
req.AssetRequestSource = source;
req.IsTextureRequest = false;
req.NumPackets = 0;
req.Params = transferRequest.TransferInfo.Params;
req.RequestAssetID = requestID;
req.TransferRequestID = transferRequest.TransferInfo.TransferID;
SendAssetNotFound(req);
return;
}
if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset)
{
requestID = new UUID(transferRequest.TransferInfo.Params, 0);
@ -12035,7 +12136,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return;
// The asset is known to exist and is in our cache, so add it to the AssetRequests list
AssetRequestToClient req = new AssetRequestToClient();
req.AssetInf = asset;
req.AssetRequestSource = source;
req.IsTextureRequest = false;
@ -12071,24 +12171,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return numPackets;
}
#region IClientIPEndpoint Members
public IPAddress EndPoint
{
get
{
if (m_userEndPoint is IPEndPoint)
{
IPEndPoint ep = (IPEndPoint)m_userEndPoint;
return ep.Address;
}
return null;
}
}
#endregion
public void SendRebakeAvatarTextures(UUID textureID)
{
RebakeAvatarTexturesPacket pack =
@ -12292,5 +12374,175 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (reply != null)
OutPacket(reply, ThrottleOutPacketType.Task);
}
public void SendRemoveInventoryItems(UUID[] items)
{
IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
if (eq == null)
{
m_log.DebugFormat("[LLCLIENT]: Null event queue");
return;
}
OSDMap llsd = new OSDMap(3);
OSDMap AgentDataMap = new OSDMap(1);
AgentDataMap.Add("AgentID", OSD.FromUUID(AgentId));
AgentDataMap.Add("SessionID", OSD.FromUUID(SessionId));
OSDArray AgentData = new OSDArray(1);
AgentData.Add(AgentDataMap);
llsd.Add("AgentData", AgentData);
OSDArray ItemData = new OSDArray();
foreach (UUID item in items)
{
OSDMap ItemDataMap = new OSDMap(2);
ItemDataMap.Add("ItemID", OSD.FromUUID(item));
ItemDataMap.Add("AgentID", OSD.FromUUID(AgentId));
ItemData.Add(ItemDataMap);
}
llsd.Add("InventoryData", ItemData);
eq.Enqueue(BuildEvent("RemoveInventoryItem",
llsd), AgentId);
}
public void SendRemoveInventoryFolders(UUID[] folders)
{
IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
if (eq == null)
{
m_log.DebugFormat("[LLCLIENT]: Null event queue");
return;
}
OSDMap llsd = new OSDMap(3);
OSDMap AgentDataMap = new OSDMap(1);
AgentDataMap.Add("AgentID", OSD.FromUUID(AgentId));
AgentDataMap.Add("SessionID", OSD.FromUUID(SessionId));
OSDArray AgentData = new OSDArray(1);
AgentData.Add(AgentDataMap);
llsd.Add("AgentData", AgentData);
OSDArray FolderData = new OSDArray();
foreach (UUID folder in folders)
{
OSDMap FolderDataMap = new OSDMap(2);
FolderDataMap.Add("FolderID", OSD.FromUUID(folder));
FolderDataMap.Add("AgentID", OSD.FromUUID(AgentId));
FolderData.Add(FolderDataMap);
}
llsd.Add("FolderData", FolderData);
eq.Enqueue(BuildEvent("RemoveInventoryFolder",
llsd), AgentId);
}
private byte[] EncodeU32(uint val)
{
byte[] ret = BitConverter.GetBytes(val);
if (BitConverter.IsLittleEndian)
Array.Reverse(ret);
return ret;
}
public void SendBulkUpdateInventory(InventoryFolderBase[] folders, InventoryItemBase[] items)
{
IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
if (eq == null)
{
m_log.DebugFormat("[LLCLIENT]: Null event queue");
return;
}
OSDMap llsd = new OSDMap(3);
OSDMap AgentDataMap = new OSDMap(1);
AgentDataMap.Add("AgentID", OSD.FromUUID(AgentId));
AgentDataMap.Add("SessionID", OSD.FromUUID(SessionId));
AgentDataMap.Add("TransactionID", OSD.FromUUID(UUID.Random()));
OSDArray AgentData = new OSDArray(1);
AgentData.Add(AgentDataMap);
llsd.Add("AgentData", AgentData);
OSDArray FolderData = new OSDArray();
foreach (InventoryFolderBase folder in folders)
{
OSDMap FolderDataMap = new OSDMap(5);
FolderDataMap.Add("FolderID", OSD.FromUUID(folder.ID));
FolderDataMap.Add("AgentID", OSD.FromUUID(AgentId));
FolderDataMap.Add("ParentID", OSD.FromUUID(folder.ParentID));
FolderDataMap.Add("Type", OSD.FromInteger(folder.Type));
FolderDataMap.Add("Name", OSD.FromString(folder.Name));
FolderData.Add(FolderDataMap);
}
llsd.Add("FolderData", FolderData);
OSDArray ItemData = new OSDArray();
foreach (InventoryItemBase item in items)
{
OSDMap ItemDataMap = new OSDMap();
ItemDataMap.Add("ItemID", OSD.FromUUID(item.ID));
ItemDataMap.Add("FolderID", OSD.FromUUID(item.Folder));
ItemDataMap.Add("CreatorID", OSD.FromUUID(item.CreatorIdAsUuid));
ItemDataMap.Add("OwnerID", OSD.FromUUID(item.Owner));
ItemDataMap.Add("GroupID", OSD.FromUUID(item.GroupID));
ItemDataMap.Add("BaseMask", OSD.FromBinary(EncodeU32((uint)item.BasePermissions)));
ItemDataMap.Add("OwnerMask", OSD.FromBinary(EncodeU32((uint)item.CurrentPermissions)));
ItemDataMap.Add("GroupMask", OSD.FromBinary(EncodeU32((uint)item.GroupPermissions)));
ItemDataMap.Add("EveryoneMask", OSD.FromBinary(EncodeU32((uint)item.EveryOnePermissions)));
ItemDataMap.Add("NextOwnerMask", OSD.FromBinary(EncodeU32((uint)item.NextPermissions)));
ItemDataMap.Add("GroupOwned", OSD.FromBoolean(item.GroupOwned));
ItemDataMap.Add("AssetID", OSD.FromUUID(item.AssetID));
ItemDataMap.Add("Type", OSD.FromInteger(item.AssetType));
ItemDataMap.Add("InvType", OSD.FromInteger(item.InvType));
ItemDataMap.Add("Flags", OSD.FromBinary(EncodeU32((uint)item.Flags)));
ItemDataMap.Add("SaleType", OSD.FromInteger((byte)item.SaleType));
ItemDataMap.Add("SalePrice", OSD.FromInteger(item.SalePrice));
ItemDataMap.Add("Name", OSD.FromString(item.Name));
ItemDataMap.Add("Description", OSD.FromString(item.Description));
ItemDataMap.Add("CreationDate", OSD.FromInteger(item.CreationDate));
ItemDataMap.Add("CRC", OSD.FromBinary(EncodeU32(
Helpers.InventoryCRC(1000, 0, (sbyte)item.InvType,
(sbyte)item.AssetType, item.AssetID,
item.GroupID, 100,
item.Owner, item.CreatorIdAsUuid,
item.ID, item.Folder,
(uint)PermissionMask.All, 1, (uint)PermissionMask.All, (uint)PermissionMask.All,
(uint)PermissionMask.All)
)));
ItemDataMap.Add("CallbackID", 0);
ItemData.Add(ItemDataMap);
}
llsd.Add("ItemData", ItemData);
eq.Enqueue(BuildEvent("BulkUpdateInventory",
llsd), AgentId);
}
}
}

View File

@ -278,7 +278,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public string GetStats()
{
return string.Format(
"{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}",
"{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7} {12,7}",
Util.EnvironmentTickCountSubtract(TickLastPacketReceived),
PacketsReceived,
PacketsSent,
PacketsResent,

View File

@ -147,21 +147,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private int m_elapsed500MSOutgoingPacketHandler;
/// <summary>Flag to signal when clients should check for resends</summary>
private bool m_resendUnacked;
protected bool m_resendUnacked;
/// <summary>Flag to signal when clients should send ACKs</summary>
private bool m_sendAcks;
protected bool m_sendAcks;
/// <summary>Flag to signal when clients should send pings</summary>
private bool m_sendPing;
protected bool m_sendPing;
private int m_defaultRTO = 0;
private int m_maxRTO = 0;
private int m_ackTimeout = 0;
private int m_pausedAckTimeout = 0;
private bool m_disableFacelights = false;
public Socket Server { get { return null; } }
private int m_malformedCount = 0; // Guard against a spamming attack
/// <summary>
/// Record current outgoing client for monitoring purposes.
/// </summary>
private IClientAPI m_currentOutgoingClient;
/// <summary>
/// Recording current incoming client for monitoring purposes.
/// </summary>
private IClientAPI m_currentIncomingClient;
public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
: base(listenIP, (int)port)
{
@ -198,11 +211,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_defaultRTO = config.GetInt("DefaultRTO", 0);
m_maxRTO = config.GetInt("MaxRTO", 0);
m_disableFacelights = config.GetBoolean("DisableFacelights", false);
m_ackTimeout = 1000 * config.GetInt("AckTimeout", 60);
m_pausedAckTimeout = 1000 * config.GetInt("PausedAckTimeout", 300);
}
else
{
PrimUpdatesPerCallback = 100;
TextureSendLimit = 20;
m_ackTimeout = 1000 * 60; // 1 minute
m_pausedAckTimeout = 1000 * 300; // 5 minutes
}
#region BinaryStats
@ -239,19 +256,56 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (m_scene == null)
throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference");
m_log.Info("[LLUDPSERVER]: Starting the LLUDP server in " + (m_asyncPacketHandling ? "asynchronous" : "synchronous") + " mode");
m_log.InfoFormat(
"[LLUDPSERVER]: Starting the LLUDP server in {0} mode",
m_asyncPacketHandling ? "asynchronous" : "synchronous");
base.Start(m_recvBufferSize, m_asyncPacketHandling);
// Start the packet processing threads
Watchdog.StartThread(
IncomingPacketHandler, "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false, true);
IncomingPacketHandler,
string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName),
ThreadPriority.Normal,
false,
true,
GetWatchdogIncomingAlarmData,
Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
Watchdog.StartThread(
OutgoingPacketHandler, "Outgoing Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false, true);
OutgoingPacketHandler,
string.Format("Outgoing Packets ({0})", m_scene.RegionInfo.RegionName),
ThreadPriority.Normal,
false,
true,
GetWatchdogOutgoingAlarmData,
Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
m_elapsedMSSinceLastStatReport = Environment.TickCount;
}
/// <summary>
/// If the outgoing UDP thread times out, then return client that was being processed to help with debugging.
/// </summary>
/// <returns></returns>
private string GetWatchdogIncomingAlarmData()
{
return string.Format(
"Client is {0}",
m_currentIncomingClient != null ? m_currentIncomingClient.Name : "none");
}
/// <summary>
/// If the outgoing UDP thread times out, then return client that was being processed to help with debugging.
/// </summary>
/// <returns></returns>
private string GetWatchdogOutgoingAlarmData()
{
return string.Format(
"Client is {0}",
m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none");
}
public new void Stop()
{
m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
@ -485,19 +539,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null);
}
public void HandleUnacked(LLUDPClient udpClient)
public void HandleUnacked(LLClientView client)
{
LLUDPClient udpClient = client.UDPClient;
if (!udpClient.IsConnected)
return;
// Disconnect an agent if no packets are received for some time
//FIXME: Make 60 an .ini setting
if ((Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > 1000 * 60)
{
m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID);
StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
int timeoutTicks = m_ackTimeout;
// Allow more slack if the client is "paused" eg file upload dialogue is open
// Some sort of limit is needed in case the client crashes, loses its network connection
// or some other disaster prevents it from sendung the AgentResume
if (udpClient.IsPaused)
timeoutTicks = m_pausedAckTimeout;
if (client.IsActive &&
(Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > timeoutTicks)
{
// We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
// though it's set later on by LLClientView.Close()
client.IsActive = false;
// Fire this out on a different thread so that we don't hold up outgoing packet processing for
// everybody else if this is being called due to an ack timeout.
// This is the same as processing as the async process of a logout request.
Util.FireAndForget(o => DeactivateClientDueToTimeout(client));
RemoveClient(udpClient);
return;
}
@ -820,7 +889,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion Ping Check Handling
// Inbox insertion
packetInbox.Enqueue(new IncomingPacket(udpClient, packet));
packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
}
#region BinaryStats
@ -916,7 +985,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
UDPPacketBuffer buffer = (UDPPacketBuffer)array[0];
UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
m_log.DebugFormat("[LLUDPSERVER]: Handling UseCircuitCode request from {0}", buffer.RemoteEndPoint);
m_log.DebugFormat(
"[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint);
remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
@ -945,8 +1016,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
// Don't create clients for unauthorized requesters.
m_log.WarnFormat(
"[LLUDPSERVER]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}",
uccp.CircuitCode.ID, uccp.CircuitCode.Code, remoteEndPoint);
"[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint);
}
// m_log.DebugFormat(
@ -1023,16 +1094,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
IClientAPI client = null;
// In priciple there shouldn't be more than one thread here, ever.
// But in case that happens, we need to synchronize this piece of code
// because it's too important
// We currently synchronize this code across the whole scene to avoid issues such as
// http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done
// consistently, this lock could probably be removed.
lock (this)
{
if (!m_scene.TryGetClient(agentID, out client))
{
LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
client.OnLogout += LogoutHandler;
((LLClientView)client).DisableFacelights = m_disableFacelights;
@ -1044,14 +1115,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return client;
}
private void RemoveClient(LLUDPClient udpClient)
/// <summary>
/// Deactivates the client if we don't receive any packets within a certain amount of time (default 60 seconds).
/// </summary>
/// <remarks>
/// If a connection is active then we will always receive packets even if nothing else is happening, due to
/// regular client pings.
/// </remarks>
/// <param name='client'></param>
private void DeactivateClientDueToTimeout(LLClientView client)
{
// Remove this client from the scene
IClientAPI client;
if (m_scene.TryGetClient(udpClient.AgentID, out client))
lock (client.CloseSyncLock)
{
client.IsLoggingOut = true;
client.Close();
m_log.WarnFormat(
"[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}",
client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName);
StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
if (!client.SceneAgent.IsChildAgent)
client.Kick("Simulator logged you out due to connection timeout");
client.CloseWithoutChecks();
}
}
@ -1159,6 +1244,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// client. m_packetSent will be set to true if a packet is sent
m_scene.ForEachClient(clientPacketHandler);
m_currentOutgoingClient = null;
// If nothing was sent, sleep for the minimum amount of time before a
// token bucket could get more tokens
if (!m_packetSent)
@ -1175,18 +1262,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Watchdog.RemoveThread();
}
private void ClientOutgoingPacketHandler(IClientAPI client)
protected void ClientOutgoingPacketHandler(IClientAPI client)
{
m_currentOutgoingClient = client;
try
{
if (client is LLClientView)
{
LLUDPClient udpClient = ((LLClientView)client).UDPClient;
LLClientView llClient = (LLClientView)client;
LLUDPClient udpClient = llClient.UDPClient;
if (udpClient.IsConnected)
{
if (m_resendUnacked)
HandleUnacked(udpClient);
HandleUnacked(llClient);
if (m_sendAcks)
SendAcks(udpClient);
@ -1202,8 +1292,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
catch (Exception ex)
{
m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name +
" threw an exception: " + ex.Message, ex);
m_log.Error(
string.Format("[LLUDPSERVER]: OutgoingPacketHandler iteration for {0} threw ", client.Name), ex);
}
}
@ -1229,11 +1319,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
nticks++;
watch1.Start();
m_currentOutgoingClient = client;
try
{
if (client is LLClientView)
{
LLUDPClient udpClient = ((LLClientView)client).UDPClient;
LLClientView llClient = (LLClientView)client;
LLUDPClient udpClient = llClient.UDPClient;
if (udpClient.IsConnected)
{
@ -1242,7 +1335,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
nticksUnack++;
watch2.Start();
HandleUnacked(udpClient);
HandleUnacked(llClient);
watch2.Stop();
avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack);
@ -1313,23 +1406,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion
private void ProcessInPacket(object state)
private void ProcessInPacket(IncomingPacket incomingPacket)
{
IncomingPacket incomingPacket = (IncomingPacket)state;
Packet packet = incomingPacket.Packet;
LLUDPClient udpClient = incomingPacket.Client;
IClientAPI client;
LLClientView client = incomingPacket.Client;
// Sanity check
if (packet == null || udpClient == null)
if (client.IsActive)
{
m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", UDPClient=\"{1}\"",
packet, udpClient);
}
m_currentIncomingClient = client;
// Make sure this client is still alive
if (m_scene.TryGetClient(udpClient.AgentID, out client))
{
try
{
// Process this packet
@ -1344,21 +1429,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
catch (Exception e)
{
// Don't let a failure in an individual client thread crash the whole sim.
m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", udpClient.AgentID, packet.Type);
m_log.Error(e.Message, e);
m_log.Error(
string.Format(
"[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw ",
client.Name, packet.Type),
e);
}
finally
{
m_currentIncomingClient = null;
}
}
else
{
m_log.DebugFormat("[LLUDPSERVER]: Dropping incoming {0} packet for dead client {1}", packet.Type, udpClient.AgentID);
m_log.DebugFormat(
"[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
packet.Type, client.Name, m_scene.RegionInfo.RegionName);
}
}
protected void LogoutHandler(IClientAPI client)
{
client.SendLogoutPacket();
if (client.IsActive)
RemoveClient(((LLClientView)client).UDPClient);
if (!client.IsLoggingOut)
{
client.IsLoggingOut = true;
client.Close();
}
}
}
}

View File

@ -45,6 +45,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
[TestFixture]
public class BasicCircuitTests
{
private Scene m_scene;
private TestLLUDPServer m_udpServer;
[TestFixtureSetUp]
public void FixtureInit()
{
@ -61,83 +64,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
}
// /// <summary>
// /// Add a client for testing
// /// </summary>
// /// <param name="scene"></param>
// /// <param name="testLLUDPServer"></param>
// /// <param name="testPacketServer"></param>
// /// <param name="acm">Agent circuit manager used in setting up the stack</param>
// protected void SetupStack(
// IScene scene, out TestLLUDPServer testLLUDPServer, out TestLLPacketServer testPacketServer,
// out AgentCircuitManager acm)
// {
// IConfigSource configSource = new IniConfigSource();
// ClientStackUserSettings userSettings = new ClientStackUserSettings();
// testLLUDPServer = new TestLLUDPServer();
// acm = new AgentCircuitManager();
//
// uint port = 666;
// testLLUDPServer.Initialise(null, ref port, 0, false, configSource, acm);
// testPacketServer = new TestLLPacketServer(testLLUDPServer, userSettings);
// testLLUDPServer.LocalScene = scene;
// }
// /// <summary>
// /// Set up a client for tests which aren't concerned with this process itself and where only one client is being
// /// tested
// /// </summary>
// /// <param name="circuitCode"></param>
// /// <param name="epSender"></param>
// /// <param name="testLLUDPServer"></param>
// /// <param name="acm"></param>
// protected void AddClient(
// uint circuitCode, EndPoint epSender, TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
// {
// UUID myAgentUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
// UUID mySessionUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
//
// AddClient(circuitCode, epSender, myAgentUuid, mySessionUuid, testLLUDPServer, acm);
// }
// /// <summary>
// /// Set up a client for tests which aren't concerned with this process itself
// /// </summary>
// /// <param name="circuitCode"></param>
// /// <param name="epSender"></param>
// /// <param name="agentId"></param>
// /// <param name="sessionId"></param>
// /// <param name="testLLUDPServer"></param>
// /// <param name="acm"></param>
// protected void AddClient(
// uint circuitCode, EndPoint epSender, UUID agentId, UUID sessionId,
// TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
// {
// AgentCircuitData acd = new AgentCircuitData();
// acd.AgentID = agentId;
// acd.SessionID = sessionId;
//
// UseCircuitCodePacket uccp = new UseCircuitCodePacket();
//
// UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
// = new UseCircuitCodePacket.CircuitCodeBlock();
// uccpCcBlock.Code = circuitCode;
// uccpCcBlock.ID = agentId;
// uccpCcBlock.SessionID = sessionId;
// uccp.CircuitCode = uccpCcBlock;
//
// acm.AddNewCircuit(circuitCode, acd);
//
// testLLUDPServer.LoadReceive(uccp, epSender);
// testLLUDPServer.ReceiveData(null);
// }
[SetUp]
public void SetUp()
{
m_scene = new SceneHelpers().SetupScene();
}
/// <summary>
/// Build an object name packet for test purposes
/// </summary>
/// <param name="objectLocalId"></param>
/// <param name="objectName"></param>
protected ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName)
private ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName)
{
ObjectNamePacket onp = new ObjectNamePacket();
ObjectNamePacket.ObjectDataBlock odb = new ObjectNamePacket.ObjectDataBlock();
@ -149,28 +87,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
return onp;
}
/// <summary>
/// Test adding a client to the stack
/// </summary>
[Test]
public void TestAddClient()
private void AddUdpServer()
{
TestHelpers.InMethod();
// XmlConfigurator.Configure();
AddUdpServer(new IniConfigSource());
}
TestScene scene = SceneHelpers.SetupScene();
uint myCircuitCode = 123456;
private void AddUdpServer(IniConfigSource configSource)
{
uint port = 0;
AgentCircuitManager acm = m_scene.AuthenticateHandler;
m_udpServer = new TestLLUDPServer(IPAddress.Any, ref port, 0, false, configSource, acm);
m_udpServer.AddScene(m_scene);
}
/// <summary>
/// Used by tests that aren't testing this stage.
/// </summary>
private ScenePresence AddClient()
{
UUID myAgentUuid = TestHelpers.ParseTail(0x1);
UUID mySessionUuid = TestHelpers.ParseTail(0x2);
uint myCircuitCode = 123456;
IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);
uint port = 0;
AgentCircuitManager acm = scene.AuthenticateHandler;
TestLLUDPServer llUdpServer
= new TestLLUDPServer(IPAddress.Any, ref port, 0, false, new IniConfigSource(), acm);
llUdpServer.AddScene(scene);
UseCircuitCodePacket uccp = new UseCircuitCodePacket();
UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
@ -185,26 +125,67 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor.
Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length);
llUdpServer.PacketReceived(upb);
AgentCircuitData acd = new AgentCircuitData();
acd.AgentID = myAgentUuid;
acd.SessionID = mySessionUuid;
m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd);
m_udpServer.PacketReceived(upb);
return m_scene.GetScenePresence(myAgentUuid);
}
/// <summary>
/// Test adding a client to the stack
/// </summary>
[Test]
public void TestAddClient()
{
TestHelpers.InMethod();
// XmlConfigurator.Configure();
AddUdpServer();
UUID myAgentUuid = TestHelpers.ParseTail(0x1);
UUID mySessionUuid = TestHelpers.ParseTail(0x2);
uint myCircuitCode = 123456;
IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);
UseCircuitCodePacket uccp = new UseCircuitCodePacket();
UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
= new UseCircuitCodePacket.CircuitCodeBlock();
uccpCcBlock.Code = myCircuitCode;
uccpCcBlock.ID = myAgentUuid;
uccpCcBlock.SessionID = mySessionUuid;
uccp.CircuitCode = uccpCcBlock;
byte[] uccpBytes = uccp.ToBytes();
UDPPacketBuffer upb = new UDPPacketBuffer(testEp, uccpBytes.Length);
upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor.
Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length);
m_udpServer.PacketReceived(upb);
// Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet
Assert.That(scene.GetScenePresence(myAgentUuid), Is.Null);
Assert.That(m_scene.GetScenePresence(myAgentUuid), Is.Null);
AgentCircuitData acd = new AgentCircuitData();
acd.AgentID = myAgentUuid;
acd.SessionID = mySessionUuid;
acm.AddNewCircuit(myCircuitCode, acd);
m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd);
llUdpServer.PacketReceived(upb);
m_udpServer.PacketReceived(upb);
// Should succeed now
ScenePresence sp = scene.GetScenePresence(myAgentUuid);
ScenePresence sp = m_scene.GetScenePresence(myAgentUuid);
Assert.That(sp.UUID, Is.EqualTo(myAgentUuid));
Assert.That(llUdpServer.PacketsSent.Count, Is.EqualTo(1));
Assert.That(m_udpServer.PacketsSent.Count, Is.EqualTo(1));
Packet packet = llUdpServer.PacketsSent[0];
Packet packet = m_udpServer.PacketsSent[0];
Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket)));
PacketAckPacket ackPacket = packet as PacketAckPacket;
@ -212,6 +193,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
Assert.That(ackPacket.Packets[0].ID, Is.EqualTo(0));
}
[Test]
public void TestLogoutClientDueToAck()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
IniConfigSource ics = new IniConfigSource();
IConfig config = ics.AddConfig("ClientStack.LindenUDP");
config.Set("AckTimeout", -1);
AddUdpServer(ics);
ScenePresence sp = AddClient();
m_udpServer.ClientOutgoingPacketHandler(sp.ControllingClient, true, false, false);
ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID);
Assert.That(spAfterAckTimeout, Is.Null);
// TestHelpers.DisableLogging();
}
// /// <summary>
// /// Test removing a client from the stack
// /// </summary>

View File

@ -79,7 +79,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
J2KDecoderModule j2kdm = new J2KDecoderModule();
scene = SceneHelpers.SetupScene();
SceneHelpers sceneHelpers = new SceneHelpers();
scene = sceneHelpers.SetupScene();
SceneHelpers.SetupSceneModules(scene, j2kdm);
tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene);

View File

@ -44,13 +44,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
}
protected int m_objectNameCallsReceived;
public MockScene()
public MockScene() : base(new RegionInfo(1000, 1000, null, null))
{
m_regInfo = new RegionInfo(1000, 1000, null, null);
m_regStatus = RegionStatus.Up;
}
public override void Update() {}
public override void Update(int frames) {}
public override void LoadWorldMap() {}
public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type)

View File

@ -59,6 +59,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
PacketsSent.Add(packet);
}
public void ClientOutgoingPacketHandler(IClientAPI client, bool resendUnacked, bool sendAcks, bool sendPing)
{
m_resendUnacked = resendUnacked;
m_sendAcks = sendAcks;
m_sendPing = sendPing;
ClientOutgoingPacketHandler(client);
}
//// /// <summary>
//// /// The chunks of data to pass to the LLUDPServer when it calls EndReceive
//// /// </summary>

View File

@ -53,9 +53,8 @@ namespace OpenSim.Region.ClientStack
protected ISimulationDataService m_simulationDataService;
protected IEstateDataService m_estateDataService;
protected ClientStackManager m_clientStackManager;
protected SceneManager m_sceneManager = new SceneManager();
public SceneManager SceneManager { get { return m_sceneManager; } }
public SceneManager SceneManager { get; protected set; }
public NetworkServersInfo NetServersInfo { get { return m_networkServersInfo; } }
public ISimulationDataService SimulationDataService { get { return m_simulationDataService; } }
public IEstateDataService EstateDataService { get { return m_estateDataService; } }
@ -77,6 +76,7 @@ namespace OpenSim.Region.ClientStack
protected override void StartupSpecific()
{
SceneManager = new SceneManager();
m_clientStackManager = CreateClientStackManager();
Initialize();
@ -94,22 +94,19 @@ namespace OpenSim.Region.ClientStack
m_log.InfoFormat("[REGION SERVER]: Starting HTTP server on port {0}", m_httpServerPort);
m_httpServer.Start();
MainServer.AddHttpServer(m_httpServer);
MainServer.Instance = m_httpServer;
// "OOB" Server
if (m_networkServersInfo.ssl_listener)
{
BaseHttpServer server = null;
server = new BaseHttpServer(
BaseHttpServer server = new BaseHttpServer(
m_networkServersInfo.https_port, m_networkServersInfo.ssl_listener, m_networkServersInfo.cert_path,
m_networkServersInfo.cert_pass);
// Add the server to m_Servers
if(server != null)
{
m_log.InfoFormat("[REGION SERVER]: Starting HTTPS server on port {0}", server.Port);
MainServer.AddHttpServer(server);
server.Start();
}
m_log.InfoFormat("[REGION SERVER]: Starting HTTPS server on port {0}", server.Port);
MainServer.AddHttpServer(server);
server.Start();
}
base.StartupSpecific();

View File

@ -42,8 +42,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
public class AssetTransactionModule : INonSharedRegionModule,
IAgentAssetTransactions
{
// private static readonly ILog m_log = LogManager.GetLogger(
// MethodBase.GetCurrentMethod().DeclaringType);
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected Scene m_Scene;
private bool m_dumpAssetsToFile = false;
@ -203,15 +202,15 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
/// and comes through this method.
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="part"></param>
/// <param name="transactionID"></param>
/// <param name="item"></param>
public void HandleTaskItemUpdateFromTransaction(IClientAPI remoteClient,
SceneObjectPart part, UUID transactionID,
TaskInventoryItem item)
public void HandleTaskItemUpdateFromTransaction(
IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item)
{
// m_log.DebugFormat(
// "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0}",
// item.Name);
m_log.DebugFormat(
"[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}",
item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName);
AgentAssetTransactions transactions =
GetUserTransactions(remoteClient.AgentId);

View File

@ -143,7 +143,7 @@ namespace Flotsam.RegionModules.AssetCache
IConfig assetConfig = source.Configs["AssetCache"];
if (assetConfig == null)
{
m_log.Warn(
m_log.Debug(
"[FLOTSAM ASSET CACHE]: AssetCache section missing from config (not copied config-include/FlotsamCache.ini.example? Using defaults.");
}
else
@ -203,10 +203,10 @@ namespace Flotsam.RegionModules.AssetCache
m_CacheDirectoryTierLen = 4;
}
MainConsole.Instance.Commands.AddCommand(Name, true, "fcache status", "fcache status", "Display cache status", HandleConsoleCommand);
MainConsole.Instance.Commands.AddCommand(Name, true, "fcache clear", "fcache clear [file] [memory]", "Remove all assets in the cache. If file or memory is specified then only this cache is cleared.", HandleConsoleCommand);
MainConsole.Instance.Commands.AddCommand(Name, true, "fcache assets", "fcache assets", "Attempt a deep scan and cache of all assets in all scenes", HandleConsoleCommand);
MainConsole.Instance.Commands.AddCommand(Name, true, "fcache expire", "fcache expire <datetime>", "Purge cached assets older then the specified date/time", HandleConsoleCommand);
MainConsole.Instance.Commands.AddCommand("Assets", true, "fcache status", "fcache status", "Display cache status", HandleConsoleCommand);
MainConsole.Instance.Commands.AddCommand("Assets", true, "fcache clear", "fcache clear [file] [memory]", "Remove all assets in the cache. If file or memory is specified then only this cache is cleared.", HandleConsoleCommand);
MainConsole.Instance.Commands.AddCommand("Assets", true, "fcache assets", "fcache assets", "Attempt a deep scan and cache of all assets in all scenes", HandleConsoleCommand);
MainConsole.Instance.Commands.AddCommand("Assets", true, "fcache expire", "fcache expire <datetime>", "Purge cached assets older then the specified date/time", HandleConsoleCommand);
}
}
}

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