Compare commits

...

88 Commits

Author SHA1 Message Date
Justin Clark-Casey (justincc) 2caa7ffd5d Fix issue where llRemoteLoadScriptPin() would treat 0 (the default) as a valid set pin in a destination prim rather than the unset no pin state
Adds regression test for this case.
2014-11-11 17:45:22 +00:00
Justin Clark-Casey (justincc) ae979199fb Allow GetTexture calls with no second value in the range header (e.g. just 5333-)
It looks like the latest Kokua is doing this.
As per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, leaving off the second value is legal
This indicates the caller wants the rest of the entity.
2012-12-12 00:48:53 +00:00
Justin Clark-Casey (justincc) 09aa87ba26 Fix SceneObjectUndoRedoTests.TestNoUndoOnObjectsNotInScene by not looking up ParentGroup scale limits if part is not in a sog 2012-11-15 02:38:57 +00:00
Justin Clark-Casey (justincc) 38fb0430bf 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:16:03 +00:00
Justin Clark-Casey (justincc) ec82e2fde8 Replace previously updated Prebuild.exe with one built directly with mono 2.4.3 2012-11-15 02:15:53 +00:00
Justin Clark-Casey (justincc) fba2864cbc 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:15:28 +00:00
Justin Clark-Casey (justincc) 15acba1972 minor: Adjust method doc on IXInventoryData MoveItem() and MoveFolder() to make it clear we're moving to an existing folder. 2012-11-14 01:53:32 +00:00
Justin Clark-Casey (justincc) 909d4dca82 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-14 01:53:23 +00:00
Justin Clark-Casey (justincc) 5676f1d037 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-14 01:52:53 +00:00
Justin Clark-Casey (justincc) d864d76254 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-14 01:52:44 +00:00
Justin Clark-Casey (justincc) ff968cbe43 refactor: Rename UserSessioNID -> UserSession in WebStatsModule since this is what it actually represents 2012-10-11 00:22:37 +01:00
Justin Clark-Casey (justincc) 582540657f Make UserSessionID a class rather than a struct, so that later updates to value suceed (rather than having to pull the data out and reinsert back into the Dictionary).
Fixes http://opensimulator.org/mantis/view.php?id=6338
2012-10-11 00:22:30 +01:00
Justin Clark-Casey (justincc) 05eeee6ee8 Add MaxPrimsUndo config setting to [Startup] section of OpenSim.ini.
This controls how many undo steps the simulator will store for each prim.
Default is now 20 rather than 5 as it briefly was.
The default number could be increased through this is a memory tradeoff which will scale with the number of prims in the sim and level of activity.
2012-10-11 00:22:23 +01:00
Justin Clark-Casey (justincc) cd6f3b147d Don't store undo states if a scene object is manipulated when it is not in a scene.
Adds regression test for this.
2012-10-11 00:22:16 +01:00
Justin Clark-Casey (justincc) 86f519ba57 refactor: Change control structures in SOP.StoreUndoState() to reduce nesting. 2012-10-11 00:22:10 +01:00
Justin Clark-Casey (justincc) febc6bae30 Make it possible to rescale SOGs when they are not in a scene. 2012-10-11 00:22:03 +01:00
Justin Clark-Casey (justincc) 48f818bf07 Enforce existing 5 action hardcoded undo limit.
This was present in the code but not enforced, which led to a memory leak over time as part properties were changed, whether by viewer, script or another source.
This commit enforces that limit, which will soon become configurable.
Regression test for undo limit added
Should help with http://opensimulator.org/mantis/view.php?id=6279
2012-10-11 00:21:56 +01:00
Justin Clark-Casey (justincc) c2d21bb8cc Add basic undo/redo regression tests. 2012-10-11 00:21:49 +01:00
Justin Clark-Casey (justincc) 39fe1ba028 Fix very recently introduced race condition where a CreateNewItem outracing an UploadAsset request could throw an exception because m_asset did not yet exist.
This was accidentally introduced in 4fc0cfb
This commit also consistently removes the AssetXferUploader when the transaction completes, no matter if it completed on asset upload or item operation.
The amount of data being retained was small, since this was clothing/bodypart metadata in the asset rather than textures themselves.
2012-10-11 00:21:39 +01:00
Justin Clark-Casey (justincc) 7112e860dc Comment out old m_storeLocal from AssetXferUploader.
This was only used if none of new item, update item or update task item had been set.
But since all transactions go through these paths this old code is redundant.
2012-10-11 00:21:30 +01:00
Justin Clark-Casey (justincc) 4606137882 Insert transaction ID into AssetXferUploader constructor rather than at UploadAsset() to prevent item creation failure when NewInventoryItem thread reachs the object first.
This was preventing the previous race condition fix in 4fc0cfb from actually working.
This commit also removes some of the pointless transaction id checks - these conditions are already being enforced in AgentAssetsTransactions.
2012-10-11 00:21:22 +01:00
Justin Clark-Casey (justincc) 8eab6b7701 Move UDP update task item code to AssetXferUploader to match existing create user item and update user item mechanisms
This is done for consistency and to allow removal or some access methods that increase code complexity.
However, this path has not been used for a long time, not even by LL 1.23 - viewers use caps http upload for this instead
2012-10-11 00:21:16 +01:00
Justin Clark-Casey (justincc) 71cd68eec1 Fix occasional race condition failure when creating new clothing/body parts in the viewer or updating existing assets.
On creating these items, the viewer sends a UDP AssetUploadRequest followed by a CreateInventoryItem.
It was possible for the CreateInventoryItem/UpdateInventoryItem to occasionally outrace the AssetUploadRequest and fail to find an initialized Xfer object, at which point the item create would fail.
So instead we always set up a Xfer object on either the asset or inventory item update request.
This does not introduce a new race because code already exists to delay the item operation until the asset is uploaded if necessary (but this only worked if the xfer object already existed)
2012-10-11 00:21:08 +01:00
Justin Clark-Casey (justincc) 168c3b78f4 Fix llListFindList() returning no match when there is a match with a script constant component in the source list.
Adds regression test for this case.
Based on http://opensimulator.org/mantis/view.php?id=6156
Thanks SignpostMarv.
2012-10-11 00:21:01 +01:00
Justin Clark-Casey (justincc) bbe04aab95 Lock GDI+ portion og VectorRenderModule.GetDrawStringSize() to prevent concurrent thread use provoking mono crashes.
Same rationale as commit 13690582.
2012-09-28 02:38:51 +01:00
Justin Clark-Casey (justincc) c27a158961 Don't fail to create an IRC nick if nick randomization is disabled in the IRC module.
Patch from http://opensimulator.org/mantis/view.php?id=6293
Thanks Starflower.
2012-09-28 00:12:54 +01:00
SignpostMarv 068e97cf0e Documentation of teleport-related events 2012-09-28 00:12:48 +01:00
SignpostMarv aa45d831f3 minor tweaks to existing comments for IDE goodness 2012-09-28 00:12:40 +01:00
SignpostMarv eff8448154 Documentation of agent-related events 2012-09-28 00:12:32 +01:00
SignpostMarv badd7f1578 Documentation of object-related events 2012-09-28 00:12:24 +01:00
SignpostMarv e12cb7bca9 Documentation of OnPluginConsole 2012-09-28 00:12:17 +01:00
Justin Clark-Casey (justincc) 23fe2a2103 Make ResendAppearanceUpdates = true by default in [Appearance] in OpenSimDefaults.ini.
This resends appearance uuids to avatars in the scene once a minute.
I have seen this help in the past resolve grey appearance problems where viewers have for unknown reasons sometimes ignored the packet.
The overhead is very small since only the UUIDs are sent - the viewer then requests the texture only if it does not have it cached.
This setting will not help with cloudy avatars which are usually due to the viewer not uploading baked texture data or uploading something that isn't valid JPEG2000
2012-09-27 23:55:15 +01:00
Justin Clark-Casey (justincc) e684e426af Add openmetaverse_data from libopenmetaverse to allow testing of texture baking via bot rather than just throwing out errors 2012-09-27 23:54:59 +01:00
Justin Clark-Casey (justincc) e65959b6f7 Add basic asset connector tests to check behaviour for normal, local and temporary assets.
Make AssetServiceConnector return more useful data on failure, such as what DLL it was trying to load
Allow LocalAssetServiceConnector.GetData() to work without a cache present, as works for the other lasc Get* methods.
2012-09-27 23:54:40 +01:00
Justin Clark-Casey (justincc) 8041af6d18 For FlotsamAssetCache, always update access times of cached scene assets before looking for files to expire.
This is to resolve a problem where an asset marked as local but not temporary but still used in the scene would be removed.
The timed expiry scan no longer tries to refetch assets from the scene that are not currently in the cache - this is not helpful since it just drags a lot of data into the cache that may never be referenced.
This removes the DeepScanBeforePurge option since setting this to false will introduce the above problem.  This previously had a default of true.
2012-09-27 23:54:32 +01:00
SignpostMarv 56873b319b Documentation of parcel-related events
Signed-off-by: BlueWall <jamesh@bluewallgroup.com>
2012-09-27 23:54:13 +01:00
SignpostMarv b315fab771 correcting a typo that causes c# express to complain about xml comment containing invalid xml
Signed-off-by: BlueWall <jamesh@bluewallgroup.com>
2012-09-27 23:54:05 +01:00
Justin Clark-Casey (justincc) 05342ed677 minor: Comment out friends notification log spam for now. 2012-09-27 23:53:47 +01:00
SignpostMarv 487bf31e06 documentation (OnSceneObjectPartCopy) 2012-09-27 23:53:20 +01:00
SignpostMarv 6f3b2ea632 documentation (OnRemovePresence) 2012-09-27 23:53:12 +01:00
SignpostMarv 307fdeff78 documentation (OnNewPresence) 2012-09-27 23:53:00 +01:00
SignpostMarv 8df3edcc30 documentation (OnClientConnect) 2012-09-27 23:52:51 +01:00
SignpostMarv a43e282efa documentation (OnBackup) 2012-09-27 23:52:34 +01:00
SignpostMarv 7374690957 documentation (OnTerrainTick) 2012-09-27 23:52:26 +01:00
SignpostMarv 0c69575670 documentation (OnTerrainTainted) 2012-09-27 23:52:19 +01:00
SignpostMarv 148cad1976 documentation (OnClientMovement) 2012-09-27 23:52:08 +01:00
SignpostMarv 7db4e00b14 Documenting some of the events on OpenSim.Region.Framework.Scenes.EventManager (OnFrame) 2012-09-27 23:51:15 +01:00
BlueWall a00f745eba Add file to .gitignore
Add OpenSim.userprefs which is created by Monodevelop to .gitignore
2012-09-27 23:50:53 +01:00
SignpostMarv 9ae335fafc adding documentation to script invokation methods 2012-09-27 23:49:06 +01:00
Justin Clark-Casey (justincc) 6bd7639d66 Also do other MySQL region settings related calls under m_dbLock, in common with other calls. 2012-09-27 23:48:51 +01:00
Justin Clark-Casey (justincc) c336309234 Do Windlight storage and removal calls in MySQL under m_dbLock, as is done with all the other database calls. 2012-09-27 23:48:45 +01:00
SignpostMarv 41d217321d fixing bug where last element in list is ignored 2012-09-27 23:48:27 +01:00
Justin Clark-Casey (justincc) a8d8ea7990 Flip release type to post fixes 2012-09-01 00:01:01 +01:00
Justin Clark-Casey (justincc) 10e6493f9f Set flavour to release. 2012-08-31 21:39:51 +01:00
Melanie 8c4f911935 Replace SendBannedUserList with Avination's version. Untested in core. Not even test compiled. 2012-08-31 16:35:36 +01:00
Justin Clark-Casey (justincc) 62bc85b5c7 Fix regression introduced in a0d178b2 (Sat Aug 25 02:00:17 2012) where folders with asset type of 'Folder' and 'Unknown' were accidentally treated as system folders.
This prevented more than one additional ordinary folder from being created in the base "My Inventory" user folder.
Added regression test for this case.
Switched tests to use XInventoryService with mostly implemented TestXInventoryDataPlugin rather than InventoryService
Disabled TestLoadIarV0_1SameNameCreator() since this has not been working for a very long time (ever since XInventoryService) started being used
since it doesnt' preserve creator data in the same way as InventoryService did and so effectively lost the OSPAs.
However, nobody noticed/complained about this issue and OSPAs have been superseded by HG like creator information via the --home save oar/iar switch.
2012-08-31 16:29:57 +01:00
SignpostMarv 76eba917f9 copying documentation from http://opensimulator.org/wiki/Threat_level 2012-08-31 16:29:46 +01:00
SignpostMarv 84a046eaf5 adding some files to .gitignore that get generated when debugging in c# express with OpenSim.32BitLaunch as the startup project 2012-08-31 16:29:40 +01:00
Justin Clark-Casey (justincc) 8d1d314f49 Add VectorRenderModule.TestRepeatSameDrawDifferentExtraParams() 2012-08-31 16:29:22 +01:00
Justin Clark-Casey (justincc) 9395f12584 Add VectorRenderModuleTests.TestRepeatDrawContainingImage() 2012-08-31 16:29:16 +01:00
Justin Clark-Casey (justincc) b97f58d597 Add VectorRenderModuleTests.TestRepeatDraw() 2012-08-31 16:29:09 +01:00
Justin Clark-Casey (justincc) 30c36a3960 Following on from f8a89a79, do not allow more than one 'type' folder (e.g. calling cards) to be created in the base "My Inventory" user folder.
This is to accomodate situations where viewers will create more than one 'type' subfolder (e.g. calling cards)
But at the same time to prevent multiple such 'system' folders (those in the base "My Inventory" user folder).
This also makes GetFolderForType() only return a folder in the base "My Inventory" folder, if such a type folder exists
2012-08-31 16:28:20 +01:00
Justin Clark-Casey (justincc) 206eccc2b6 Allow multiple calling card type inventory folders to be created.
Modern viewers want to create Friends and All folders of this type inside the root Calling Cards folder.
2012-08-31 16:28:13 +01:00
Justin Clark-Casey (justincc) 2358a623e3 minor: Fix bad log message for failure to create an inventory folder 2012-08-31 16:28:04 +01:00
Justin Clark-Casey (justincc) 87850bd6dc Log initial script startup info notice when xengine actually starts to do this for debugging purposes, rather than before it actually starts to do this. 2012-08-31 16:27:54 +01:00
Justin Clark-Casey (justincc) d80eda202f Extend "Restarting scripts in attachments" debug log message to show actual name of user and the region they are in 2012-08-24 22:57:18 +01:00
Justin Clark-Casey (justincc) 3edfa585ec If a connecting scene presence is replacing an existing scene presence then bypass close checks. 2012-08-24 22:43:14 +01:00
Justin Clark-Casey (justincc) fa13a6a8da Bump version number to 0.7.4-rc2 2012-08-24 22:07:58 +01:00
Justin Clark-Casey (justincc) 9d5e7c89d9 Pass the "attachToBackup" bool given to SceneGraph.AddNewSceneObject() down into the 3-parameter AddNewSceneObject() method instead of always hardcoding true.
This doesn't affect any core OpenSimulator code since all callers were passing true anyway
But it allows region modules to create objects that are never persisted.
2012-08-24 21:53:57 +01:00
SignpostMarv 590bf0bcc0 adding sqlite journal files to .gitignore 2012-08-24 21:53:46 +01:00
Justin Clark-Casey (justincc) b199a2dea3 If a script state save fails for some reason on shutdown/region removal, get xengine to spit out some useful information and continue to save other script states 2012-08-24 21:53:22 +01:00
Justin Clark-Casey (justincc) f1d4b8d83e Add an [HGAssetService] section to SQLiteStandalone.ini with the same connection string as [AssetService].
This is necessary because commit 8131a24 (Tue Mar 27 10:08:13 2012) started passing the config section name rather than hardcoding "AssetService"
This meant that the HG external-facing asset service tried to read ConnectionString from [HGAssetService] rather than [AssetService].
On SQLite, not finding this meant that it fell back to [DatabaseService], which is set for OpenSim.db rather than Asset.db.
Therefore, all external asset requests returned null.
Solution taken here is to create an [HGAssetService] section with the same ConnectionString as [AssetService].
This bug does not affect normal MySQL/MSSQL config since they use the [DatabaseService] connection string anyway.
Addresses http://opensimulator.org/mantis/view.php?id=6200, many thanks to DanBanner for identifying the exact problem commit which was very helpful.
This was a regression from OpenSimulator 0.7.3.1 which did not contain this bug.
2012-08-24 21:53:12 +01:00
Justin Clark-Casey (justincc) 0088661356 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-24 21:53:01 +01:00
Justin Clark-Casey (justincc) 1a7e3cabc0 Fix bug in SoundModule.PlayAttachedSound() 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 is similar to commit d89faa which fixed the same kind of bug in TriggerSound()
2012-08-24 21:52:51 +01:00
Justin Clark-Casey (justincc) 132d701b3e 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-24 21:52:30 +01:00
Justin Clark-Casey (justincc) 3b97241716 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-24 21:52:21 +01:00
Melanie f82d090df3 Fix llDialog responses so that they can be heard throughout the region. This now conforms to the behaviour in SL. 2012-08-24 21:52:12 +01:00
Justin Clark-Casey (justincc) 7399d3e953 When reporting a thread timeout, create a copy of the info rather than passing the original ThreadWatchdogInfo structure.
This is to avoid the possibility of misleading reporting if a watchdog update outraces an alarm.
Should address any remaining issues from http://opensimulator.org/mantis/view.php?id=6012
2012-08-24 21:51:03 +01:00
Justin Clark-Casey (justincc) cab546ecee Add information to ThreadStackSize about possibly increasing if suffering StackOverflowExceptions during script conversion/compilation (e.g. on Windows 64-bit) 2012-08-24 21:50:49 +01:00
Justin Clark-Casey (justincc) 7dc1c7d841 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-24 21:50:40 +01:00
Robert Adams fbff51f387 Correct an exception report in SceneObjectPart so it outputs the stack. 2012-08-24 21:50:03 +01:00
SignpostMarv b714fb0c39 Implementing PRIM_LINK_TARGET in a non-recursive fashion 2012-08-24 21:49:44 +01:00
Justin Clark-Casey (justincc) f37038013d Don't enable the thread watchdog until all regions are ready.
This is to avoid false positives when the machine is under heavy load whilst starting up.
2012-08-24 21:49:36 +01:00
SignpostMarv 5e98e2b7c7 adding ATTACH_*_PEC constants 2012-08-24 21:49:27 +01:00
Justin Clark-Casey (justincc) 35f8f3ff79 minor: Add Gryc Ueusp to CREDITS for commit 884edac amongst others, by request. 2012-08-24 21:48:59 +01:00
Justin Clark-Casey (justincc) 7ec8e7e025 Prevent race conditions when one thread removes an NPC SP before another thread has retreived it after checking whether the NPC exists. 2012-08-24 21:48:48 +01:00
Melanie c6efebdd8c Release http-in URLs when llResetScript is called 2012-08-24 21:48:15 +01:00
Justin Clark-Casey (justincc) 760047abc5 Flip version to 0.7.4-rc1 2012-08-03 23:58:34 +01:00
136 changed files with 14932 additions and 1033 deletions

6
.gitignore vendored
View File

@ -26,9 +26,14 @@
bin/Debug/*.dll bin/Debug/*.dll
bin/*.dll.mdb bin/*.dll.mdb
bin/*.db bin/*.db
bin/*.db-journal
bin/addin-db-* bin/addin-db-*
bin/*.dll bin/*.dll
bin/OpenSim.vshost.exe.config bin/OpenSim.vshost.exe.config
bin/OpenSim.32BitLaunch.vshost.exe.config
bin/OpenSim.32BitLaunch.log
UpgradeLog.XML
_UpgradeReport_Files/
bin/ScriptEngines/*-*-*-*-* bin/ScriptEngines/*-*-*-*-*
bin/ScriptEngines/*.dll bin/ScriptEngines/*.dll
bin/ScriptEngines/*/*.dll bin/ScriptEngines/*/*.dll
@ -61,6 +66,7 @@ Examples/*.dll
OpenSim.build OpenSim.build
OpenSim.sln OpenSim.sln
OpenSim.suo OpenSim.suo
OpenSim.userprefs
Prebuild/Prebuild.build Prebuild/Prebuild.build
Prebuild/Prebuild.sln Prebuild/Prebuild.sln
TestResult.xml TestResult.xml

View File

@ -91,6 +91,7 @@ what it is today.
* Fly-Man * Fly-Man
* Flyte Xevious * Flyte Xevious
* Garmin Kawaguichi * Garmin Kawaguichi
* Gryc Ueusp
* Imaze Rhiano * Imaze Rhiano
* Intimidated * Intimidated
* Jeremy Bongio (IBM) * Jeremy Bongio (IBM)

View File

@ -228,6 +228,11 @@ namespace OpenSim.Capabilities.Handlers
} }
else else
{ {
// Handle the case where no second range value was given. This is equivalent to requesting
// the rest of the entity.
if (end == -1)
end = int.MaxValue;
end = Utils.Clamp(end, 0, texture.Data.Length - 1); end = Utils.Clamp(end, 0, texture.Data.Length - 1);
start = Utils.Clamp(start, 0, end); start = Utils.Clamp(start, 0, end);
int len = end - start + 1; int len = end - start + 1;
@ -275,16 +280,44 @@ namespace OpenSim.Capabilities.Handlers
// texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length); // texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
} }
/// <summary>
/// Parse a range header.
/// </summary>
/// <remarks>
/// As per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html,
/// this obeys range headers with two values (e.g. 533-4165) and no second value (e.g. 533-).
/// Where there is no value, -1 is returned.
/// FIXME: Need to cover the case where only a second value is specified (e.g. -4165), probably by returning -1
/// for start.</remarks>
/// <returns></returns>
/// <param name='header'></param>
/// <param name='start'>Undefined if the parse fails.</param>
/// <param name='end'>Undefined if the parse fails.</param>
private bool TryParseRange(string header, out int start, out int end) private bool TryParseRange(string header, out int start, out int end)
{ {
start = end = 0;
if (header.StartsWith("bytes=")) if (header.StartsWith("bytes="))
{ {
string[] rangeValues = header.Substring(6).Split('-'); string[] rangeValues = header.Substring(6).Split('-');
if (rangeValues.Length == 2) if (rangeValues.Length == 2)
{ {
if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end)) if (!Int32.TryParse(rangeValues[0], out start))
return false;
string rawEnd = rangeValues[1];
if (rawEnd == "")
{
end = -1;
return true; return true;
} }
else if (Int32.TryParse(rawEnd, out end))
{
return true;
}
}
} }
start = end = 0; start = end = 0;

View File

@ -40,6 +40,11 @@ namespace OpenSim.Data
public UUID folderID; public UUID folderID;
public UUID agentID; public UUID agentID;
public UUID parentFolderID; public UUID parentFolderID;
public XInventoryFolder Clone()
{
return (XInventoryFolder)MemberwiseClone();
}
} }
public class XInventoryItem public class XInventoryItem
@ -64,6 +69,11 @@ namespace OpenSim.Data
public UUID avatarID; public UUID avatarID;
public UUID parentFolderID; public UUID parentFolderID;
public int inventoryGroupPermissions; public int inventoryGroupPermissions;
public XInventoryItem Clone()
{
return (XInventoryItem)MemberwiseClone();
}
} }
public interface IXInventoryData public interface IXInventoryData
@ -106,7 +116,22 @@ namespace OpenSim.Data
/// <returns>true if the delete was successful, false if it was not</returns> /// <returns>true if the delete was successful, false if it was not</returns>
bool DeleteItems(string[] fields, string[] vals); 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); XInventoryItem[] GetActiveGestures(UUID principalID);
int GetAssetPermissions(UUID principalID, UUID assetID); int GetAssetPermissions(UUID principalID, UUID assetID);
} }

View File

@ -43,12 +43,12 @@ namespace OpenSim.Data.MSSQL
// private static readonly ILog m_log = LogManager.GetLogger( // private static readonly ILog m_log = LogManager.GetLogger(
// MethodBase.GetCurrentMethod().DeclaringType); // MethodBase.GetCurrentMethod().DeclaringType);
private MSSQLGenericTableHandler<XInventoryFolder> m_Folders; private MSSQLFolderHandler m_Folders;
private MSSQLItemHandler m_Items; private MSSQLItemHandler m_Items;
public MSSQLXInventoryData(string conn, string realm) public MSSQLXInventoryData(string conn, string realm)
{ {
m_Folders = new MSSQLGenericTableHandler<XInventoryFolder>( m_Folders = new MSSQLFolderHandler(
conn, "inventoryfolders", "InventoryStore"); conn, "inventoryfolders", "InventoryStore");
m_Items = new MSSQLItemHandler( m_Items = new MSSQLItemHandler(
conn, "inventoryitems", String.Empty); conn, "inventoryitems", String.Empty);
@ -85,6 +85,7 @@ namespace OpenSim.Data.MSSQL
{ {
return m_Folders.Delete(field, val); return m_Folders.Delete(field, val);
} }
public bool DeleteFolders(string[] fields, string[] vals) public bool DeleteFolders(string[] fields, string[] vals)
{ {
return m_Folders.Delete(fields, vals); return m_Folders.Delete(fields, vals);
@ -94,15 +95,22 @@ namespace OpenSim.Data.MSSQL
{ {
return m_Items.Delete(field, val); return m_Items.Delete(field, val);
} }
public bool DeleteItems(string[] fields, string[] vals) public bool DeleteItems(string[] fields, string[] vals)
{ {
return m_Items.Delete(fields, vals); return m_Items.Delete(fields, vals);
} }
public bool MoveItem(string id, string newParent) public bool MoveItem(string id, string newParent)
{ {
return m_Items.MoveItem(id, 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) public XInventoryItem[] GetActiveGestures(UUID principalID)
{ {
return m_Items.GetActiveGestures(principalID); return m_Items.GetActiveGestures(principalID);
@ -124,6 +132,7 @@ namespace OpenSim.Data.MSSQL
public bool MoveItem(string id, string newParent) public bool MoveItem(string id, string newParent)
{ {
using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
{
using (SqlCommand cmd = new SqlCommand()) using (SqlCommand cmd = new SqlCommand())
{ {
@ -135,10 +144,12 @@ namespace OpenSim.Data.MSSQL
return cmd.ExecuteNonQuery() == 0 ? false : true; return cmd.ExecuteNonQuery() == 0 ? false : true;
} }
} }
}
public XInventoryItem[] GetActiveGestures(UUID principalID) public XInventoryItem[] GetActiveGestures(UUID principalID)
{ {
using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
{
using (SqlCommand cmd = new SqlCommand()) using (SqlCommand cmd = new SqlCommand())
{ {
cmd.CommandText = String.Format("select * from inventoryitems where avatarId = @uuid and assetType = @type and flags = 1", m_Realm); cmd.CommandText = String.Format("select * from inventoryitems where avatarId = @uuid and assetType = @type and flags = 1", m_Realm);
@ -150,10 +161,12 @@ namespace OpenSim.Data.MSSQL
return DoQuery(cmd); return DoQuery(cmd);
} }
} }
}
public int GetAssetPermissions(UUID principalID, UUID assetID) public int GetAssetPermissions(UUID principalID, UUID assetID)
{ {
using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
{
using (SqlCommand cmd = new SqlCommand()) 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.CommandText = String.Format("select bit_or(inventoryCurrentPermissions) as inventoryCurrentPermissions from inventoryitems where avatarID = @PrincipalID and assetID = @AssetID group by assetID", m_Realm);
@ -176,12 +189,16 @@ namespace OpenSim.Data.MSSQL
} }
} }
}
public override bool Store(XInventoryItem item) public override bool Store(XInventoryItem item)
{ {
if (!base.Store(item)) if (!base.Store(item))
return false; return false;
string sql = "update inventoryfolders set version=version+1 where folderID = @folderID"; string sql = "update inventoryfolders set version=version+1 where folderID = @folderID";
using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
{
using (SqlCommand cmd = new SqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
conn.Open(); conn.Open();
@ -196,7 +213,34 @@ namespace OpenSim.Data.MSSQL
return false; return false;
} }
} }
return true; 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;
}
}
}
}
} }

View File

@ -219,6 +219,8 @@ namespace OpenSim.Data.MySQL
public virtual bool Store(T row) public virtual bool Store(T row)
{ {
// m_log.DebugFormat("[MYSQL GENERIC TABLE HANDLER]: Store(T row) invoked");
using (MySqlCommand cmd = new MySqlCommand()) using (MySqlCommand cmd = new MySqlCommand())
{ {
string query = ""; string query = "";
@ -273,6 +275,10 @@ namespace OpenSim.Data.MySQL
public virtual bool Delete(string[] fields, string[] keys) 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) if (fields.Length != keys.Length)
return false; return false;

View File

@ -719,6 +719,8 @@ namespace OpenSim.Data.MySQL
RegionLightShareData nWP = new RegionLightShareData(); RegionLightShareData nWP = new RegionLightShareData();
nWP.OnSave += StoreRegionWindlightSettings; nWP.OnSave += StoreRegionWindlightSettings;
lock (m_dbLock)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{ {
dbcon.Open(); dbcon.Open();
@ -808,6 +810,8 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
return nWP; return nWP;
} }
@ -852,6 +856,8 @@ namespace OpenSim.Data.MySQL
} }
public void StoreRegionWindlightSettings(RegionLightShareData wl) public void StoreRegionWindlightSettings(RegionLightShareData wl)
{
lock (m_dbLock)
{ {
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{ {
@ -953,8 +959,11 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
public void RemoveRegionWindlightSettings(UUID regionID) public void RemoveRegionWindlightSettings(UUID regionID)
{
lock (m_dbLock)
{ {
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{ {
@ -968,9 +977,12 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
#region RegionEnvironmentSettings #region RegionEnvironmentSettings
public string LoadRegionEnvironmentSettings(UUID regionUUID) public string LoadRegionEnvironmentSettings(UUID regionUUID)
{
lock (m_dbLock)
{ {
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{ {
@ -996,8 +1008,11 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings) public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
{
lock (m_dbLock)
{ {
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{ {
@ -1014,8 +1029,11 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
public void RemoveRegionEnvironmentSettings(UUID regionUUID) public void RemoveRegionEnvironmentSettings(UUID regionUUID)
{
lock (m_dbLock)
{ {
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{ {
@ -1029,6 +1047,7 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
#endregion #endregion
public void StoreRegionSettings(RegionSettings rs) public void StoreRegionSettings(RegionSettings rs)

View File

@ -26,9 +26,10 @@
*/ */
using System; using System;
using System.Data;
using System.Reflection;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using log4net; using log4net;
using MySql.Data.MySqlClient; using MySql.Data.MySqlClient;
using OpenMetaverse; using OpenMetaverse;
@ -41,12 +42,12 @@ namespace OpenSim.Data.MySQL
/// </summary> /// </summary>
public class MySQLXInventoryData : IXInventoryData public class MySQLXInventoryData : IXInventoryData
{ {
private MySQLGenericTableHandler<XInventoryFolder> m_Folders; private MySqlFolderHandler m_Folders;
private MySqlItemHandler m_Items; private MySqlItemHandler m_Items;
public MySQLXInventoryData(string conn, string realm) public MySQLXInventoryData(string conn, string realm)
{ {
m_Folders = new MySQLGenericTableHandler<XInventoryFolder>( m_Folders = new MySqlFolderHandler(
conn, "inventoryfolders", "InventoryStore"); conn, "inventoryfolders", "InventoryStore");
m_Items = new MySqlItemHandler( m_Items = new MySqlItemHandler(
conn, "inventoryitems", String.Empty); conn, "inventoryitems", String.Empty);
@ -105,6 +106,11 @@ namespace OpenSim.Data.MySQL
return m_Items.MoveItem(id, 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) public XInventoryItem[] GetActiveGestures(UUID principalID)
{ {
return m_Items.GetActiveGestures(principalID); return m_Items.GetActiveGestures(principalID);
@ -118,22 +124,69 @@ namespace OpenSim.Data.MySQL
public class MySqlItemHandler : MySQLGenericTableHandler<XInventoryItem> public class MySqlItemHandler : MySQLGenericTableHandler<XInventoryItem>
{ {
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public MySqlItemHandler(string c, string t, string m) : public MySqlItemHandler(string c, string t, string m) :
base(c, t, 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) 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()) using (MySqlCommand cmd = new MySqlCommand())
{ {
cmd.CommandText = String.Format("update {0} set parentFolderID = ?ParentFolderID where inventoryID = ?InventoryID", m_Realm); cmd.CommandText = String.Format("update {0} set parentFolderID = ?ParentFolderID where inventoryID = ?InventoryID", m_Realm);
cmd.Parameters.AddWithValue("?ParentFolderID", newParent); cmd.Parameters.AddWithValue("?ParentFolderID", newParent);
cmd.Parameters.AddWithValue("?InventoryID", id); 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) public XInventoryItem[] GetActiveGestures(UUID principalID)
@ -184,6 +237,21 @@ namespace OpenSim.Data.MySQL
if (!base.Store(item)) if (!base.Store(item))
return false; 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)) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{ {
dbcon.Open(); dbcon.Open();
@ -193,7 +261,7 @@ namespace OpenSim.Data.MySQL
cmd.Connection = dbcon; cmd.Connection = dbcon;
cmd.CommandText = String.Format("update inventoryfolders set version=version+1 where folderID = ?folderID"); 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 try
{ {
@ -205,8 +273,95 @@ namespace OpenSim.Data.MySQL
} }
cmd.Dispose(); cmd.Dispose();
} }
dbcon.Close(); 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; return true;
} }
} }

View File

@ -47,7 +47,7 @@ namespace OpenSim.Data.SQLite
{ {
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private SQLiteGenericTableHandler<XInventoryFolder> m_Folders; private SqliteFolderHandler m_Folders;
private SqliteItemHandler m_Items; private SqliteItemHandler m_Items;
public SQLiteXInventoryData(string conn, string realm) public SQLiteXInventoryData(string conn, string realm)
@ -55,7 +55,7 @@ namespace OpenSim.Data.SQLite
if (Util.IsWindows()) if (Util.IsWindows())
Util.LoadArchSpecificWindowsDll("sqlite3.dll"); Util.LoadArchSpecificWindowsDll("sqlite3.dll");
m_Folders = new SQLiteGenericTableHandler<XInventoryFolder>( m_Folders = new SqliteFolderHandler(
conn, "inventoryfolders", "XInventoryStore"); conn, "inventoryfolders", "XInventoryStore");
m_Items = new SqliteItemHandler( m_Items = new SqliteItemHandler(
conn, "inventoryitems", String.Empty); conn, "inventoryitems", String.Empty);
@ -114,6 +114,11 @@ namespace OpenSim.Data.SQLite
return m_Items.MoveItem(id, 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) public XInventoryItem[] GetActiveGestures(UUID principalID)
{ {
return m_Items.GetActiveGestures(principalID); return m_Items.GetActiveGestures(principalID);
@ -177,4 +182,23 @@ namespace OpenSim.Data.SQLite
return perms; 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

@ -199,7 +199,14 @@ namespace OpenSim.Framework
// //
public class Cache public class Cache
{ {
/// <summary>
/// Must only be accessed under lock.
/// </summary>
private List<CacheItemBase> m_Index = new List<CacheItemBase>(); private List<CacheItemBase> m_Index = new List<CacheItemBase>();
/// <summary>
/// Must only be accessed under m_Index lock.
/// </summary>
private Dictionary<string, CacheItemBase> m_Lookup = private Dictionary<string, CacheItemBase> m_Lookup =
new Dictionary<string, CacheItemBase>(); new Dictionary<string, CacheItemBase>();
@ -320,7 +327,6 @@ namespace OpenSim.Framework
{ {
if (m_Lookup.ContainsKey(index)) if (m_Lookup.ContainsKey(index))
item = m_Lookup[index]; item = m_Lookup[index];
}
if (item == null) if (item == null)
{ {
@ -332,6 +338,7 @@ namespace OpenSim.Framework
item.lastUsed = DateTime.Now; item.lastUsed = DateTime.Now;
Expire(true); Expire(true);
}
return item; return item;
} }
@ -385,7 +392,10 @@ namespace OpenSim.Framework
// //
public Object Find(Predicate<CacheItemBase> d) 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) if (item == null)
return null; return null;
@ -419,12 +429,12 @@ namespace OpenSim.Framework
public virtual void Store(string index, Object data, Type container, public virtual void Store(string index, Object data, Type container,
Object[] parameters) Object[] parameters)
{ {
Expire(false);
CacheItemBase item; CacheItemBase item;
lock (m_Index) lock (m_Index)
{ {
Expire(false);
if (m_Index.Contains(new CacheItemBase(index))) if (m_Index.Contains(new CacheItemBase(index)))
{ {
if ((m_Flags & CacheFlags.AllowUpdate) != 0) if ((m_Flags & CacheFlags.AllowUpdate) != 0)
@ -450,9 +460,17 @@ namespace OpenSim.Framework
m_Index.Add(item); m_Index.Add(item);
m_Lookup[index] = item; m_Lookup[index] = item;
} }
item.Store(data); 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) protected virtual void Expire(bool getting)
{ {
if (getting && (m_Strategy == CacheStrategy.Aggressive)) if (getting && (m_Strategy == CacheStrategy.Aggressive))
@ -479,8 +497,6 @@ namespace OpenSim.Framework
if (Count < Size) if (Count < Size)
return; return;
lock (m_Index)
{
m_Index.Sort(new SortLRU()); m_Index.Sort(new SortLRU());
m_Index.Reverse(); m_Index.Reverse();
@ -513,14 +529,17 @@ namespace OpenSim.Framework
foreach (CacheItemBase item in m_Index) foreach (CacheItemBase item in m_Index)
m_Lookup[item.uuid] = item; m_Lookup[item.uuid] = item;
} }
}
break; break;
default: default:
break; break;
} }
} }
public void Invalidate(string uuid) public void Invalidate(string uuid)
{
lock (m_Index)
{ {
if (!m_Lookup.ContainsKey(uuid)) if (!m_Lookup.ContainsKey(uuid))
return; return;
@ -529,11 +548,15 @@ namespace OpenSim.Framework
m_Lookup.Remove(uuid); m_Lookup.Remove(uuid);
m_Index.Remove(item); m_Index.Remove(item);
} }
}
public void Clear() public void Clear()
{
lock (m_Index)
{ {
m_Index.Clear(); m_Index.Clear();
m_Lookup.Clear(); m_Lookup.Clear();
} }
} }
}
} }

View File

@ -1033,7 +1033,21 @@ namespace OpenSim.Framework
void InPacket(object NewPack); void InPacket(object NewPack);
void ProcessInPacket(Packet NewPack); void ProcessInPacket(Packet NewPack);
/// <summary>
/// Close this client
/// </summary>
void Close(); 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); void Kick(string message);
/// <summary> /// <summary>

View File

@ -73,32 +73,26 @@ namespace OpenSim.Framework
{ {
} }
public InventoryFolderBase(UUID id) public InventoryFolderBase(UUID id) : this()
{ {
ID = id; ID = id;
} }
public InventoryFolderBase(UUID id, UUID owner) public InventoryFolderBase(UUID id, UUID owner) : this(id)
{ {
ID = id;
Owner = owner; Owner = owner;
} }
public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) : this(id, owner)
{ {
ID = id;
Name = name; Name = name;
Owner = owner;
ParentID = parent; ParentID = parent;
} }
public InventoryFolderBase(UUID id, string name, UUID owner, short type, UUID parent, ushort version) public InventoryFolderBase(
UUID id, string name, UUID owner, short type, UUID parent, ushort version) : this(id, name, owner, parent)
{ {
ID = id;
Name = name;
Owner = owner;
Type = type; Type = type;
ParentID = parent;
Version = version; Version = version;
} }
} }

View File

@ -89,6 +89,17 @@ namespace OpenSim.Framework.Monitoring
FirstTick = Environment.TickCount & Int32.MaxValue; FirstTick = Environment.TickCount & Int32.MaxValue;
LastTick = FirstTick; LastTick = FirstTick;
} }
public ThreadWatchdogInfo(ThreadWatchdogInfo previousTwi)
{
Thread = previousTwi.Thread;
FirstTick = previousTwi.FirstTick;
LastTick = previousTwi.LastTick;
Timeout = previousTwi.Timeout;
IsTimedOut = previousTwi.IsTimedOut;
AlarmIfTimeout = previousTwi.AlarmIfTimeout;
AlarmMethod = previousTwi.AlarmMethod;
}
} }
/// <summary> /// <summary>
@ -97,6 +108,32 @@ namespace OpenSim.Framework.Monitoring
/// /summary> /// /summary>
public static event Action<ThreadWatchdogInfo> OnWatchdogTimeout; public static event Action<ThreadWatchdogInfo> OnWatchdogTimeout;
/// <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)
return;
m_enabled = value;
if (m_enabled)
{
// Set now so we don't get alerted on the first run
LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue;
}
m_watchdogTimer.Enabled = m_enabled;
}
}
private static bool m_enabled;
private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private static Dictionary<int, ThreadWatchdogInfo> m_threads; private static Dictionary<int, ThreadWatchdogInfo> m_threads;
private static System.Timers.Timer m_watchdogTimer; private static System.Timers.Timer m_watchdogTimer;
@ -115,11 +152,6 @@ namespace OpenSim.Framework.Monitoring
m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS); m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS);
m_watchdogTimer.AutoReset = false; m_watchdogTimer.AutoReset = false;
m_watchdogTimer.Elapsed += WatchdogTimerElapsed; m_watchdogTimer.Elapsed += WatchdogTimerElapsed;
// Set now so we don't get alerted on the first run
LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue;
m_watchdogTimer.Start();
} }
/// <summary> /// <summary>
@ -314,7 +346,9 @@ namespace OpenSim.Framework.Monitoring
if (callbackInfos == null) if (callbackInfos == null)
callbackInfos = new List<ThreadWatchdogInfo>(); callbackInfos = new List<ThreadWatchdogInfo>();
callbackInfos.Add(threadInfo); // Send a copy of the watchdog info to prevent race conditions where the watchdog
// thread updates the monitoring info after an alarm has been sent out.
callbackInfos.Add(new ThreadWatchdogInfo(threadInfo));
} }
} }
} }

View File

@ -65,9 +65,14 @@ namespace OpenSim.Framework.Serialization
UserAccount account = userService.GetUserAccount(UUID.Zero, userId); UserAccount account = userService.GetUserAccount(UUID.Zero, userId);
if (account != null) if (account != null)
{
return MakeOspa(account.FirstName, account.LastName); return MakeOspa(account.FirstName, account.LastName);
}
// else // else
// {
// m_log.WarnFormat("[OSP RESOLVER]: No user account for {0}", userId); // m_log.WarnFormat("[OSP RESOLVER]: No user account for {0}", userId);
// System.Console.WriteLine("[OSP RESOLVER]: No user account for {0}", userId);
// }
return null; return null;
} }
@ -79,10 +84,13 @@ namespace OpenSim.Framework.Serialization
/// <returns></returns> /// <returns></returns>
public static string MakeOspa(string firstName, string lastName) public static string MakeOspa(string firstName, string lastName)
{ {
// m_log.DebugFormat("[OSP RESOLVER]: Making OSPA for {0} {1}", firstName, lastName); string ospa
= OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName;
return // m_log.DebugFormat("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName);
OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName; // System.Console.WriteLine("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName);
return ospa;
} }
/// <summary> /// <summary>

View File

@ -30,7 +30,7 @@ namespace OpenSim
public class VersionInfo public class VersionInfo
{ {
private const string VERSION_NUMBER = "0.7.4"; private const string VERSION_NUMBER = "0.7.4";
private const Flavour VERSION_FLAVOUR = Flavour.Dev; private const Flavour VERSION_FLAVOUR = Flavour.Post_Fixes;
public enum Flavour public enum Flavour
{ {

View File

@ -35,6 +35,7 @@ using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Timers; using System.Timers;
using log4net; using log4net;
using NDesk.Options;
using Nini.Config; using Nini.Config;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
@ -310,8 +311,11 @@ namespace OpenSim
"Change the scale of a named prim", HandleEditScale); "Change the scale of a named prim", HandleEditScale);
m_console.Commands.AddCommand("Users", false, "kick user", m_console.Commands.AddCommand("Users", false, "kick user",
"kick user <first> <last> [message]", "kick user <first> <last> [--force] [message]",
"Kick a user off the simulator", KickUserCommand); "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("Users", false, "show users", m_console.Commands.AddCommand("Users", false, "show users",
"show users [full]", "show users [full]",
@ -453,11 +457,17 @@ namespace OpenSim
/// <param name="cmdparams">name of avatar to kick</param> /// <param name="cmdparams">name of avatar to kick</param>
private void KickUserCommand(string module, string[] cmdparams) 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; return;
string alert = null; string alert = null;
if (cmdparams.Length > 4) if (mainParams.Count > 4)
alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4));
IList agents = SceneManager.GetCurrentSceneAvatars(); IList agents = SceneManager.GetCurrentSceneAvatars();
@ -466,8 +476,8 @@ namespace OpenSim
{ {
RegionInfo regionInfo = presence.Scene.RegionInfo; RegionInfo regionInfo = presence.Scene.RegionInfo;
if (presence.Firstname.ToLower().Contains(cmdparams[2].ToLower()) && if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) &&
presence.Lastname.ToLower().Contains(cmdparams[3].ToLower())) presence.Lastname.ToLower().Contains(mainParams[3].ToLower()))
{ {
MainConsole.Instance.Output( MainConsole.Instance.Output(
String.Format( String.Format(
@ -480,7 +490,7 @@ namespace OpenSim
else else
presence.ControllingClient.Kick("\nThe OpenSim manager kicked you out.\n"); presence.ControllingClient.Kick("\nThe OpenSim manager kicked you out.\n");
presence.Scene.IncomingCloseAgent(presence.UUID); presence.Scene.IncomingCloseAgent(presence.UUID, force);
} }
} }

View File

@ -305,8 +305,13 @@ namespace OpenSim
m_httpServerPort = m_networkServersInfo.HttpListenerPort; m_httpServerPort = m_networkServersInfo.HttpListenerPort;
SceneManager.OnRestartSim += handleRestartRegion; SceneManager.OnRestartSim += handleRestartRegion;
// Only start the memory watchdog once all regions are ready // Only enable the watchdogs when all regions are ready. Otherwise we get false positives when cpu is
SceneManager.OnRegionsReadyStatusChange += sm => MemoryWatchdog.Enabled = sm.AllRegionsReady; // heavily used during initial startup.
//
// FIXME: It's also possible that region ready status should be flipped during an OAR load since this
// also makes heavy use of the CPU.
SceneManager.OnRegionsReadyStatusChange
+= sm => { MemoryWatchdog.Enabled = sm.AllRegionsReady; Watchdog.Enabled = sm.AllRegionsReady; };
} }
/// <summary> /// <summary>

View File

@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
UUID spId = TestHelpers.ParseTail(0x1); UUID spId = TestHelpers.ParseTail(0x1);
SceneHelpers.AddScenePresence(m_scene, spId); 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 // TODO: Add more assertions for the other aspects of event queues
Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0));

View File

@ -487,16 +487,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region Client Methods #region Client Methods
/// <summary>
/// Close down the client view
/// </summary>
public void Close() 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. // 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. // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
lock (CloseSyncLock) lock (CloseSyncLock)
{ {
if (!IsActive) // 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; return;
IsActive = false; IsActive = false;
@ -4447,8 +4451,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (bl[i].BannedUserID == UUID.Zero) if (bl[i].BannedUserID == UUID.Zero)
continue; continue;
BannedUsers.Add(bl[i].BannedUserID); BannedUsers.Add(bl[i].BannedUserID);
}
if (BannedUsers.Count >= 50 || (i == (bl.Length - 1) && BannedUsers.Count > 0))
{
EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
packet.AgentData.TransactionID = UUID.Random(); packet.AgentData.TransactionID = UUID.Random();
packet.AgentData.AgentID = AgentId; packet.AgentData.AgentID = AgentId;
@ -4458,11 +4463,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count]; EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count];
for (int i = 0; i < (6 + BannedUsers.Count); i++) int j;
for (j = 0; j < (6 + BannedUsers.Count); j++)
{ {
returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock();
} }
int j = 0; j = 0;
returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
@ -4476,8 +4482,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
returnblock[j].Parameter = banned.GetBytes(); j++; returnblock[j].Parameter = banned.GetBytes(); j++;
} }
packet.ParamList = returnblock; packet.ParamList = returnblock;
packet.Header.Reliable = false; packet.Header.Reliable = true;
OutPacket(packet, ThrottleOutPacketType.Task); OutPacket(packet, ThrottleOutPacketType.Task);
BannedUsers.Clear();
}
}
} }
public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args) public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args)
@ -5810,7 +5821,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
args.Channel = ch; args.Channel = ch;
args.From = String.Empty; args.From = String.Empty;
args.Message = Utils.BytesToString(msg); args.Message = Utils.BytesToString(msg);
args.Type = ChatTypeEnum.Shout; args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
args.Position = new Vector3(); args.Position = new Vector3();
args.Scene = Scene; args.Scene = Scene;
args.Sender = this; args.Sender = this;
@ -11989,7 +12000,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
Kick(reason); Kick(reason);
Thread.Sleep(1000); Thread.Sleep(1000);
Close(); Disconnect();
} }
public void Disconnect() public void Disconnect()

View File

@ -57,40 +57,37 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
} }
/// <summary> /// <summary>
/// Return a xfer uploader if one does not already exist. /// Return the xfer uploader for the given transaction.
/// </summary> /// </summary>
/// <remarks>
/// If an uploader does not already exist for this transaction then it is created, otherwise the existing
/// uploader is returned.
/// </remarks>
/// <param name="transactionID"></param> /// <param name="transactionID"></param>
/// <param name="assetID"> /// <returns>The asset xfer uploader</returns>
/// We must transfer the new asset ID into the uploader on creation, otherwise public AssetXferUploader RequestXferUploader(UUID transactionID)
/// we can see race conditions with other threads which can retrieve an item before it is updated with the new
/// asset id.
/// </param>
/// <returns>
/// The xfer uploader requested. Null if one is already in existence.
/// FIXME: This is a bizarre thing to do, and is probably meant to signal an error condition if multiple
/// transfers are made. Needs to be corrected.
/// </returns>
public AssetXferUploader RequestXferUploader(UUID transactionID, UUID assetID)
{ {
AssetXferUploader uploader;
lock (XferUploaders) lock (XferUploaders)
{ {
if (!XferUploaders.ContainsKey(transactionID)) if (!XferUploaders.ContainsKey(transactionID))
{ {
AssetXferUploader uploader = new AssetXferUploader(this, m_Scene, assetID, m_dumpAssetsToFile); uploader = new AssetXferUploader(this, m_Scene, transactionID, m_dumpAssetsToFile);
// m_log.DebugFormat( // m_log.DebugFormat(
// "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID); // "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID);
XferUploaders.Add(transactionID, uploader); XferUploaders.Add(transactionID, uploader);
}
else
{
uploader = XferUploaders[transactionID];
}
}
return uploader; return uploader;
} }
}
m_log.WarnFormat("[AGENT ASSETS TRANSACTIONS]: Ignoring request for asset xfer uploader {0} since it already exists", transactionID);
return null;
}
public void HandleXfer(ulong xferID, uint packetID, byte[] data) public void HandleXfer(ulong xferID, uint packetID, byte[] data)
{ {
@ -151,115 +148,28 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
string description, string name, sbyte invType, string description, string name, sbyte invType,
sbyte type, byte wearableType, uint nextOwnerMask) sbyte type, byte wearableType, uint nextOwnerMask)
{ {
AssetXferUploader uploader = null; AssetXferUploader uploader = RequestXferUploader(transactionID);
lock (XferUploaders)
{
if (XferUploaders.ContainsKey(transactionID))
uploader = XferUploaders[transactionID];
}
if (uploader != null)
uploader.RequestCreateInventoryItem( uploader.RequestCreateInventoryItem(
remoteClient, transactionID, folderID, remoteClient, folderID, callbackID,
callbackID, description, name, invType, type, description, name, invType, type, wearableType, nextOwnerMask);
wearableType, nextOwnerMask);
else
m_log.ErrorFormat(
"[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to create inventory item {1} from {2}",
transactionID, name, remoteClient.Name);
}
/// <summary>
/// Get an uploaded asset. If the data is successfully retrieved,
/// the transaction will be removed.
/// </summary>
/// <param name="transactionID"></param>
/// <returns>The asset if the upload has completed, null if it has not.</returns>
private AssetBase GetTransactionAsset(UUID transactionID)
{
lock (XferUploaders)
{
if (XferUploaders.ContainsKey(transactionID))
{
AssetXferUploader uploader = XferUploaders[transactionID];
AssetBase asset = uploader.GetAssetData();
RemoveXferUploader(transactionID);
return asset;
}
}
return null;
} }
public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient,
SceneObjectPart part, UUID transactionID, SceneObjectPart part, UUID transactionID,
TaskInventoryItem item) TaskInventoryItem item)
{ {
AssetXferUploader uploader = null; AssetXferUploader uploader = RequestXferUploader(transactionID);
lock (XferUploaders) uploader.RequestUpdateTaskInventoryItem(remoteClient, item);
{
if (XferUploaders.ContainsKey(transactionID))
uploader = XferUploaders[transactionID];
}
if (uploader != null)
{
AssetBase asset = GetTransactionAsset(transactionID);
// Only legacy viewers use this, and they prefer CAPS, which
// we have, so this really never runs.
// Allow it, but only for "safe" types.
if ((InventoryType)item.InvType != InventoryType.Notecard &&
(InventoryType)item.InvType != InventoryType.LSL)
return;
if (asset != null)
{
// m_log.DebugFormat(
// "[AGENT ASSETS TRANSACTIONS]: Updating item {0} in {1} for transaction {2}",
// item.Name, part.Name, transactionID);
asset.FullID = UUID.Random();
asset.Name = item.Name;
asset.Description = item.Description;
asset.Type = (sbyte)item.Type;
item.AssetID = asset.FullID;
m_Scene.AssetService.Store(asset);
}
}
else
{
m_log.ErrorFormat(
"[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update task inventory item {1} in {2}",
transactionID, item.Name, part.Name);
}
} }
public void RequestUpdateInventoryItem(IClientAPI remoteClient, public void RequestUpdateInventoryItem(IClientAPI remoteClient,
UUID transactionID, InventoryItemBase item) UUID transactionID, InventoryItemBase item)
{ {
AssetXferUploader uploader = null; AssetXferUploader uploader = RequestXferUploader(transactionID);
lock (XferUploaders) uploader.RequestUpdateInventoryItem(remoteClient, item);
{
if (XferUploaders.ContainsKey(transactionID))
uploader = XferUploaders[transactionID];
}
if (uploader != null)
{
uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item);
}
else
{
m_log.ErrorFormat(
"[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update inventory item {1} for {2}",
transactionID, item.Name, remoteClient.Name);
}
} }
} }
} }

View File

@ -215,7 +215,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item)
{ {
m_log.DebugFormat( m_log.DebugFormat(
"[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", "[ASSET TRANSACTION MODULE] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}",
item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName); item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName);
AgentAssetTransactions transactions = AgentAssetTransactions transactions =
@ -274,13 +274,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
} }
AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
AssetXferUploader uploader = transactions.RequestXferUploader(transaction, assetID); AssetXferUploader uploader = transactions.RequestXferUploader(transaction);
uploader.StartUpload(remoteClient, assetID, transaction, type, data, storeLocal, tempFile);
if (uploader != null)
{
uploader.Initialise(remoteClient, assetID, transaction, type,
data, storeLocal, tempFile);
}
} }
/// <summary> /// <summary>

View File

@ -40,39 +40,75 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// Upload state.
/// </summary>
/// <remarks>
/// New -> Uploading -> Complete
/// </remarks>
private enum UploadState
{
New,
Uploading,
Complete
}
/// <summary> /// <summary>
/// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we
/// are performing a delayed update. /// are performing a delayed update.
/// </summary> /// </summary>
AgentAssetTransactions m_transactions; AgentAssetTransactions m_transactions;
private UploadState m_uploadState = UploadState.New;
private AssetBase m_asset; private AssetBase m_asset;
private UUID InventFolder = UUID.Zero; private UUID InventFolder = UUID.Zero;
private sbyte invType = 0; private sbyte invType = 0;
private bool m_createItem = false; private bool m_createItem;
private uint m_createItemCallback = 0; private uint m_createItemCallback;
private bool m_updateItem = false;
private bool m_updateItem;
private InventoryItemBase m_updateItemData; private InventoryItemBase m_updateItemData;
private bool m_updateTaskItem;
private TaskInventoryItem m_updateTaskItemData;
private string m_description = String.Empty; private string m_description = String.Empty;
private bool m_dumpAssetToFile; private bool m_dumpAssetToFile;
private bool m_finished = false;
private string m_name = String.Empty; private string m_name = String.Empty;
private bool m_storeLocal; // private bool m_storeLocal;
private uint nextPerm = 0; private uint nextPerm = 0;
private IClientAPI ourClient; private IClientAPI ourClient;
private UUID TransactionID = UUID.Zero;
private UUID m_transactionID;
private sbyte type = 0; private sbyte type = 0;
private byte wearableType = 0; private byte wearableType = 0;
public ulong XferID; public ulong XferID;
private Scene m_Scene; private Scene m_Scene;
public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile) /// <summary>
/// AssetXferUploader constructor
/// </summary>
/// <param name='transactions'>/param>
/// <param name='scene'></param>
/// <param name='transactionID'></param>
/// <param name='dumpAssetToFile'>
/// If true then when the asset is uploaded it is dumped to a file with the format
/// String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat",
/// now.Year, now.Month, now.Day, now.Hour, now.Minute,
/// now.Second, m_asset.Name, m_asset.Type);
/// for debugging purposes.
/// </param>
public AssetXferUploader(
AgentAssetTransactions transactions, Scene scene, UUID transactionID, bool dumpAssetToFile)
{ {
m_asset = new AssetBase();
m_transactions = transactions; m_transactions = transactions;
m_transactionID = transactionID;
m_Scene = scene; m_Scene = scene;
m_asset = new AssetBase() { FullID = assetID };
m_dumpAssetToFile = dumpAssetToFile; m_dumpAssetToFile = dumpAssetToFile;
} }
@ -118,30 +154,50 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
} }
/// <summary> /// <summary>
/// Initialise asset transfer from the client /// Start asset transfer from the client
/// </summary> /// </summary>
/// <param name="xferID"></param> /// <param name="remoteClient"></param>
/// <param name="packetID"></param> /// <param name="assetID"></param>
/// <param name="data"></param> /// <param name="transaction"></param>
public void Initialise(IClientAPI remoteClient, UUID assetID, /// <param name="type"></param>
UUID transaction, sbyte type, byte[] data, bool storeLocal, /// <param name="data">
/// Optional data. If present then the asset is created immediately with this data
/// rather than requesting an upload from the client. The data must be longer than 2 bytes.
/// </param>
/// <param name="storeLocal"></param>
/// <param name="tempFile"></param>
public void StartUpload(
IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, byte[] data, bool storeLocal,
bool tempFile) bool tempFile)
{ {
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}", // "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}",
// remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length); // remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length);
lock (this)
{
if (m_uploadState != UploadState.New)
{
m_log.WarnFormat(
"[ASSET XFER UPLOADER]: Tried to start upload of asset {0}, transaction {1} for {2} but this is already in state {3}. Aborting.",
assetID, transaction, remoteClient.Name, m_uploadState);
return;
}
m_uploadState = UploadState.Uploading;
}
ourClient = remoteClient; ourClient = remoteClient;
m_asset.Name = "blank";
m_asset.Description = "empty"; m_asset.FullID = assetID;
m_asset.Type = type; m_asset.Type = type;
m_asset.CreatorID = remoteClient.AgentId.ToString(); m_asset.CreatorID = remoteClient.AgentId.ToString();
m_asset.Data = data; m_asset.Data = data;
m_asset.Local = storeLocal; m_asset.Local = storeLocal;
m_asset.Temporary = tempFile; m_asset.Temporary = tempFile;
TransactionID = transaction; // m_storeLocal = storeLocal;
m_storeLocal = storeLocal;
if (m_asset.Data.Length > 2) if (m_asset.Data.Length > 2)
{ {
@ -166,36 +222,35 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
protected void SendCompleteMessage() protected void SendCompleteMessage()
{ {
ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true,
m_asset.FullID);
// We must lock in order to avoid a race with a separate thread dealing with an inventory item or create // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create
// message from other client UDP. // message from other client UDP.
lock (this) lock (this)
{ {
m_finished = true; m_uploadState = UploadState.Complete;
ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID);
if (m_createItem) if (m_createItem)
{ {
DoCreateItem(m_createItemCallback); CompleteCreateItem(m_createItemCallback);
} }
else if (m_updateItem) else if (m_updateItem)
{ {
StoreAssetForItemUpdate(m_updateItemData); CompleteItemUpdate(m_updateItemData);
// Remove ourselves from the list of transactions if completion was delayed until the transaction
// was complete.
// TODO: Should probably do the same for create item.
m_transactions.RemoveXferUploader(TransactionID);
} }
else if (m_storeLocal) else if (m_updateTaskItem)
{ {
m_Scene.AssetService.Store(m_asset); CompleteTaskItemUpdate(m_updateTaskItemData);
} }
// else if (m_storeLocal)
// {
// m_Scene.AssetService.Store(m_asset);
// }
} }
m_log.DebugFormat( m_log.DebugFormat(
"[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}", "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}",
m_asset.FullID, TransactionID); m_asset.FullID, m_transactionID);
if (m_dumpAssetToFile) if (m_dumpAssetToFile)
{ {
@ -223,11 +278,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
} }
public void RequestCreateInventoryItem(IClientAPI remoteClient, public void RequestCreateInventoryItem(IClientAPI remoteClient,
UUID transactionID, UUID folderID, uint callbackID, UUID folderID, uint callbackID,
string description, string name, sbyte invType, string description, string name, sbyte invType,
sbyte type, byte wearableType, uint nextOwnerMask) sbyte type, byte wearableType, uint nextOwnerMask)
{
if (TransactionID == transactionID)
{ {
InventFolder = folderID; InventFolder = folderID;
m_name = name; m_name = name;
@ -243,9 +296,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
// We must lock to avoid a race with a separate thread uploading the asset. // We must lock to avoid a race with a separate thread uploading the asset.
lock (this) lock (this)
{ {
if (m_finished) if (m_uploadState == UploadState.Complete)
{ {
DoCreateItem(callbackID); CompleteCreateItem(callbackID);
} }
else else
{ {
@ -254,9 +307,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
} }
} }
} }
}
public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) public void RequestUpdateInventoryItem(IClientAPI remoteClient, InventoryItemBase item)
{ {
// We must lock to avoid a race with a separate thread uploading the asset. // We must lock to avoid a race with a separate thread uploading the asset.
lock (this) lock (this)
@ -271,9 +323,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
item.AssetID = m_asset.FullID; item.AssetID = m_asset.FullID;
m_Scene.InventoryService.UpdateItem(item); m_Scene.InventoryService.UpdateItem(item);
if (m_finished) if (m_uploadState == UploadState.Complete)
{ {
StoreAssetForItemUpdate(item); CompleteItemUpdate(item);
} }
else else
{ {
@ -287,20 +339,59 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
} }
} }
public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, TaskInventoryItem taskItem)
{
// We must lock to avoid a race with a separate thread uploading the asset.
lock (this)
{
m_asset.Name = taskItem.Name;
m_asset.Description = taskItem.Description;
m_asset.Type = (sbyte)taskItem.Type;
taskItem.AssetID = m_asset.FullID;
if (m_uploadState == UploadState.Complete)
{
CompleteTaskItemUpdate(taskItem);
}
else
{
m_updateTaskItem = true;
m_updateTaskItemData = taskItem;
}
}
}
/// <summary> /// <summary>
/// Store the asset for the given item. /// Store the asset for the given item when it has been uploaded.
/// </summary> /// </summary>
/// <param name="item"></param> /// <param name="item"></param>
private void StoreAssetForItemUpdate(InventoryItemBase item) private void CompleteItemUpdate(InventoryItemBase item)
{ {
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", // "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}",
// m_asset.FullID, item.Name, ourClient.Name); // m_asset.FullID, item.Name, ourClient.Name);
m_Scene.AssetService.Store(m_asset); m_Scene.AssetService.Store(m_asset);
m_transactions.RemoveXferUploader(m_transactionID);
} }
private void DoCreateItem(uint callbackID) /// <summary>
/// Store the asset for the given task item when it has been uploaded.
/// </summary>
/// <param name="taskItem"></param>
private void CompleteTaskItemUpdate(TaskInventoryItem taskItem)
{
// m_log.DebugFormat(
// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}",
// m_asset.FullID, taskItem.Name, ourClient.Name);
m_Scene.AssetService.Store(m_asset);
m_transactions.RemoveXferUploader(m_transactionID);
}
private void CompleteCreateItem(uint callbackID)
{ {
m_Scene.AssetService.Store(m_asset); m_Scene.AssetService.Store(m_asset);
@ -326,20 +417,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
ourClient.SendInventoryItemCreateUpdate(item, callbackID); ourClient.SendInventoryItemCreateUpdate(item, callbackID);
else else
ourClient.SendAlertMessage("Unable to create inventory item"); ourClient.SendAlertMessage("Unable to create inventory item");
}
/// <summary> m_transactions.RemoveXferUploader(m_transactionID);
/// Get the asset data uploaded in this transfer.
/// </summary>
/// <returns>null if the asset has not finished uploading</returns>
public AssetBase GetAssetData()
{
if (m_finished)
{
return m_asset;
}
return null;
} }
} }
} }

View File

@ -107,8 +107,6 @@ namespace Flotsam.RegionModules.AssetCache
private IAssetService m_AssetService; private IAssetService m_AssetService;
private List<Scene> m_Scenes = new List<Scene>(); private List<Scene> m_Scenes = new List<Scene>();
private bool m_DeepScanBeforePurge;
public FlotsamAssetCache() public FlotsamAssetCache()
{ {
m_InvalidChars.AddRange(Path.GetInvalidPathChars()); m_InvalidChars.AddRange(Path.GetInvalidPathChars());
@ -170,8 +168,6 @@ namespace Flotsam.RegionModules.AssetCache
m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen); m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen);
m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt); m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt);
m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", m_DeepScanBeforePurge);
} }
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory); m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory);
@ -506,13 +502,10 @@ namespace Flotsam.RegionModules.AssetCache
// Purge all files last accessed prior to this point // Purge all files last accessed prior to this point
DateTime purgeLine = DateTime.Now - m_FileExpiration; DateTime purgeLine = DateTime.Now - m_FileExpiration;
// An optional deep scan at this point will ensure assets present in scenes, // An asset cache may contain local non-temporary assets that are not in the asset service. Therefore,
// or referenced by objects in the scene, but not recently accessed // before cleaning up expired files we must scan the objects in the scene to make sure that we retain
// are not purged. // such local assets if they have not been recently accessed.
if (m_DeepScanBeforePurge) TouchAllSceneAssets(false);
{
CacheScenes();
}
foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) foreach (string dir in Directory.GetDirectories(m_CacheDirectory))
{ {
@ -705,11 +698,14 @@ namespace Flotsam.RegionModules.AssetCache
/// <summary> /// <summary>
/// Iterates through all Scenes, doing a deep scan through assets /// Iterates through all Scenes, doing a deep scan through assets
/// to cache all assets present in the scene or referenced by assets /// to update the access time of all assets present in the scene or referenced by assets
/// in the scene /// in the scene.
/// </summary> /// </summary>
/// <returns></returns> /// <param name="storeUncached">
private int CacheScenes() /// If true, then assets scanned which are not found in cache are added to the cache.
/// </param>
/// <returns>Number of distinct asset references found in the scene.</returns>
private int TouchAllSceneAssets(bool storeUncached)
{ {
UuidGatherer gatherer = new UuidGatherer(m_AssetService); UuidGatherer gatherer = new UuidGatherer(m_AssetService);
@ -732,7 +728,7 @@ namespace Flotsam.RegionModules.AssetCache
{ {
File.SetLastAccessTime(filename, DateTime.Now); File.SetLastAccessTime(filename, DateTime.Now);
} }
else else if (storeUncached)
{ {
m_AssetService.Get(assetID.ToString()); m_AssetService.Get(assetID.ToString());
} }
@ -860,13 +856,14 @@ namespace Flotsam.RegionModules.AssetCache
break; break;
case "assets": case "assets":
m_log.Info("[FLOTSAM ASSET CACHE]: Caching all assets, in all scenes."); m_log.Info("[FLOTSAM ASSET CACHE]: Ensuring assets are cached for all scenes.");
Util.FireAndForget(delegate { Util.FireAndForget(delegate {
int assetsCached = CacheScenes(); int assetReferenceTotal = TouchAllSceneAssets(true);
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Completed Scene Caching, {0} assets found.", assetsCached); m_log.InfoFormat(
"[FLOTSAM ASSET CACHE]: Completed check with {0} assets.",
assetReferenceTotal);
}); });
break; break;

View File

@ -461,7 +461,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; SceneObjectGroup rezzedAtt = presence.GetAttachments()[0];
scene.IncomingCloseAgent(presence.UUID); scene.IncomingCloseAgent(presence.UUID, false);
// Check that we can't retrieve this attachment from the scene. // Check that we can't retrieve this attachment from the scene.
Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null);

View File

@ -482,9 +482,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
Util.FireAndForget( Util.FireAndForget(
delegate delegate
{ {
m_log.DebugFormat( // m_log.DebugFormat(
"[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}", // "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}",
friendList.Count, agentID, online); // friendList.Count, agentID, online);
// Notify about this user status // Notify about this user status
StatusNotify(friendList, agentID, online); StatusNotify(friendList, agentID, online);

View File

@ -350,38 +350,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID));
} }
/// <summary> // /// <summary>
/// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where // /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
/// an account exists with the same name as the creator, though not the same id. // /// an account exists with the same name as the creator, though not the same id.
/// </summary> // /// </summary>
[Test] // [Test]
public void TestLoadIarV0_1SameNameCreator() // public void TestLoadIarV0_1SameNameCreator()
{ // {
TestHelpers.InMethod(); // TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure(); // TestHelpers.EnableLogging();
//
UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); // UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood");
UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); // UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire");
//
m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); // m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream);
InventoryItemBase foundItem1 // InventoryItemBase foundItem1
= InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); // = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
//
Assert.That( // Assert.That(
foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), // foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()),
"Loaded item non-uuid creator doesn't match original"); // "Loaded item non-uuid creator doesn't match original");
Assert.That( // Assert.That(
foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), // foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID),
"Loaded item uuid creator doesn't match original"); // "Loaded item uuid creator doesn't match original");
Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), // Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID),
"Loaded item owner doesn't match inventory reciever"); // "Loaded item owner doesn't match inventory reciever");
//
AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); // AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
string xmlData = Utils.BytesToString(asset1.Data); // string xmlData = Utils.BytesToString(asset1.Data);
SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); // SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
//
Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); // Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID));
} // }
/// <summary> /// <summary>
/// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where

View File

@ -644,7 +644,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// an agent cannot teleport back to this region if it has teleported away. // an agent cannot teleport back to this region if it has teleported away.
Thread.Sleep(2000); Thread.Sleep(2000);
sp.Scene.IncomingCloseAgent(sp.UUID); sp.Scene.IncomingCloseAgent(sp.UUID, false);
} }
else else
{ {

View File

@ -45,31 +45,129 @@ using OpenSim.Tests.Common.Mock;
namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
{ {
[TestFixture] [TestFixture]
public class VectorRenderModuleTests public class VectorRenderModuleTests : OpenSimTestCase
{ {
Scene m_scene;
DynamicTextureModule m_dtm;
VectorRenderModule m_vrm;
[SetUp]
public void SetUp()
{
m_scene = new SceneHelpers().SetupScene();
m_dtm = new DynamicTextureModule();
m_vrm = new VectorRenderModule();
SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm);
}
[Test] [Test]
public void TestDraw() public void TestDraw()
{ {
TestHelpers.InMethod(); TestHelpers.InMethod();
Scene scene = new SceneHelpers().SetupScene(); SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
DynamicTextureModule dtm = new DynamicTextureModule();
VectorRenderModule vrm = new VectorRenderModule();
SceneHelpers.SetupSceneModules(scene, dtm, vrm);
SceneObjectGroup so = SceneHelpers.AddSceneObject(scene);
UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
dtm.AddDynamicTextureData( m_dtm.AddDynamicTextureData(
scene.RegionInfo.RegionID, m_scene.RegionInfo.RegionID,
so.UUID, so.UUID,
vrm.GetContentType(), m_vrm.GetContentType(),
"PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
"", "",
0); 0);
Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
} }
[Test]
public void TestRepeatSameDraw()
{
TestHelpers.InMethod();
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
}
[Test]
public void TestRepeatSameDrawDifferentExtraParams()
{
TestHelpers.InMethod();
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"alpha:250",
0);
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
}
[Test]
public void TestRepeatSameDrawContainingImage()
{
TestHelpers.InMethod();
string dtText
= "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
}
} }
} }

View File

@ -97,10 +97,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
public void GetDrawStringSize(string text, string fontName, int fontSize, public void GetDrawStringSize(string text, string fontName, int fontSize,
out double xSize, out double ySize) out double xSize, out double ySize)
{
lock (this)
{ {
using (Font myFont = new Font(fontName, fontSize)) using (Font myFont = new Font(fontName, fontSize))
{ {
SizeF stringSize = new SizeF(); SizeF stringSize = new SizeF();
// XXX: This lock may be unnecessary.
lock (m_graph) lock (m_graph)
{ {
stringSize = m_graph.MeasureString(text, myFont); stringSize = m_graph.MeasureString(text, myFont);
@ -109,6 +113,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
} }
} }
} }
}
#endregion #endregion
@ -307,6 +312,13 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
Graphics graph = null; Graphics graph = null;
try try
{
// XXX: 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.
lock (this)
{ {
if (alpha == 256) if (alpha == 256)
bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
@ -337,6 +349,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
} }
GDIDraw(data, graph, altDataDelim); GDIDraw(data, graph, altDataDelim);
}
byte[] imageJ2000 = new byte[0]; byte[] imageJ2000 = new byte[0];
@ -354,6 +367,13 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
m_textureManager.ReturnData(id, imageJ2000); m_textureManager.ReturnData(id, imageJ2000);
} }
finally finally
{
// XXX: 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.
lock (this)
{ {
if (graph != null) if (graph != null)
graph.Dispose(); graph.Dispose();
@ -362,6 +382,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
bitmap.Dispose(); bitmap.Dispose();
} }
} }
}
private int parseIntParam(string strInt) private int parseIntParam(string strInt)
{ {

View File

@ -205,7 +205,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
{ {
// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id); // m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id);
AssetBase asset = m_Cache.Get(id); AssetBase asset = null;
if (m_Cache != null)
asset = m_Cache.Get(id);
if (asset != null) if (asset != null)
return asset.Data; return asset.Data;

View File

@ -0,0 +1,136 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;
using log4net.Config;
using Nini.Config;
using NUnit.Framework;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset;
using OpenSim.Tests.Common;
namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
{
[TestFixture]
public class AssetConnectorsTests : OpenSimTestCase
{
[Test]
public void TestAddAsset()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
IConfigSource config = new IniConfigSource();
config.AddConfig("Modules");
config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
config.AddConfig("AssetService");
config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
lasc.Initialise(config);
AssetBase a1 = AssetHelpers.CreateNotecardAsset();
lasc.Store(a1);
AssetBase retreivedA1 = lasc.Get(a1.ID);
Assert.That(retreivedA1.ID, Is.EqualTo(a1.ID));
Assert.That(retreivedA1.Metadata.ID, Is.EqualTo(a1.Metadata.ID));
Assert.That(retreivedA1.Data.Length, Is.EqualTo(a1.Data.Length));
AssetMetadata retrievedA1Metadata = lasc.GetMetadata(a1.ID);
Assert.That(retrievedA1Metadata.ID, Is.EqualTo(a1.ID));
byte[] retrievedA1Data = lasc.GetData(a1.ID);
Assert.That(retrievedA1Data.Length, Is.EqualTo(a1.Data.Length));
// TODO: Add cache and check that this does receive a copy of the asset
}
[Test]
public void TestAddTemporaryAsset()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
IConfigSource config = new IniConfigSource();
config.AddConfig("Modules");
config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
config.AddConfig("AssetService");
config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
lasc.Initialise(config);
AssetBase a1 = AssetHelpers.CreateNotecardAsset();
a1.Temporary = true;
lasc.Store(a1);
Assert.That(lasc.Get(a1.ID), Is.Null);
Assert.That(lasc.GetData(a1.ID), Is.Null);
Assert.That(lasc.GetMetadata(a1.ID), Is.Null);
// TODO: Add cache and check that this does receive a copy of the asset
}
[Test]
public void TestAddLocalAsset()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
IConfigSource config = new IniConfigSource();
config.AddConfig("Modules");
config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
config.AddConfig("AssetService");
config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
lasc.Initialise(config);
AssetBase a1 = AssetHelpers.CreateNotecardAsset();
a1.Local = true;
lasc.Store(a1);
Assert.That(lasc.Get(a1.ID), Is.Null);
Assert.That(lasc.GetData(a1.ID), Is.Null);
Assert.That(lasc.GetMetadata(a1.ID), Is.Null);
// TODO: Add cache and check that this does receive a copy of the asset
}
}
}

View File

@ -312,7 +312,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", // "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
// s.RegionInfo.RegionName, destination.RegionHandle); // s.RegionInfo.RegionName, destination.RegionHandle);
Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id); }); Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id, false); });
return true; return true;
} }

View File

@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.World.Land
/// without recounting the whole sim. /// without recounting the whole sim.
/// ///
/// We start out tainted so that the first get call resets the various prim counts. /// We start out tainted so that the first get call resets the various prim counts.
/// <value> /// </value>
private bool m_Tainted = true; private bool m_Tainted = true;
private Object m_TaintLock = new Object(); private Object m_TaintLock = new Object();

View File

@ -85,13 +85,15 @@ namespace OpenSim.Region.CoreModules.World.Sound
dis = 0; dis = 0;
} }
float thisSpGain;
// Scale by distance // Scale by distance
if (radius == 0) if (radius == 0)
gain = (float)((double)gain * ((100.0 - dis) / 100.0)); thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0));
else else
gain = (float)((double)gain * ((radius - dis) / radius)); thisSpGain = (float)((double)gain * ((radius - dis) / radius));
sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)gain, flags); sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, thisSpGain, flags);
}); });
} }

View File

@ -46,9 +46,31 @@ namespace OpenSim.Region.Framework.Interfaces
/// </summary> /// </summary>
event ScriptCommand OnScriptCommand; event ScriptCommand OnScriptCommand;
/// <summary>
/// Register an instance method as a script call by method name
/// </summary>
/// <param name="target"></param>
/// <param name="method"></param>
void RegisterScriptInvocation(object target, string method); void RegisterScriptInvocation(object target, string method);
/// <summary>
/// Register an instance method as a script call by method info
/// </summary>
/// <param name="target"></param>
/// <param name="method"></param>
void RegisterScriptInvocation(object target, MethodInfo method); void RegisterScriptInvocation(object target, MethodInfo method);
/// <summary>
/// Register one or more instance methods as script calls by method name
/// </summary>
/// <param name="target"></param>
/// <param name="methods"></param>
void RegisterScriptInvocation(object target, string[] methods); void RegisterScriptInvocation(object target, string[] methods);
/// <summary>
/// Returns an array of all registered script calls
/// </summary>
/// <returns></returns>
Delegate[] GetScriptInvocationList(); Delegate[] GetScriptInvocationList();
Delegate LookupScriptInvocation(string fname); Delegate LookupScriptInvocation(string fname);

View File

@ -47,26 +47,71 @@ namespace OpenSim.Region.Framework.Scenes
public delegate void OnFrameDelegate(); public delegate void OnFrameDelegate();
/// <summary>
/// Triggered on each sim frame.
/// </summary>
/// <remarks>
/// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.Update"/>
/// Core uses it for things like Sun, Wind & Clouds
/// The MRM module also uses it.
/// </remarks>
public event OnFrameDelegate OnFrame; public event OnFrameDelegate OnFrame;
public delegate void ClientMovement(ScenePresence client); public delegate void ClientMovement(ScenePresence client);
/// <summary>
/// Trigerred when an agent moves.
/// </summary>
/// <remarks>
/// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.ScenePresence.HandleAgentUpdate"/>
/// prior to <see cref="OpenSim.Region.Framework.Scenes.ScenePresence.TriggerScenePresenceUpdated"/>
/// </remarks>
public event ClientMovement OnClientMovement; public event ClientMovement OnClientMovement;
public delegate void OnTerrainTaintedDelegate(); public delegate void OnTerrainTaintedDelegate();
/// <summary>
/// Triggered if the terrain has been edited
/// </summary>
/// <remarks>
/// This gets triggered in <see cref="OpenSim.Region.CoreModules.World.Terrain.CheckForTerrainUpdates"/>
/// after it determines that an update has been made.
/// </remarks>
public event OnTerrainTaintedDelegate OnTerrainTainted; public event OnTerrainTaintedDelegate OnTerrainTainted;
public delegate void OnTerrainTickDelegate(); public delegate void OnTerrainTickDelegate();
/// <summary>
/// Triggered if the terrain has been edited
/// </summary>
/// <remarks>
/// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.UpdateTerrain"/>
/// but is used by core solely to update the physics engine.
/// </remarks>
public event OnTerrainTickDelegate OnTerrainTick; public event OnTerrainTickDelegate OnTerrainTick;
public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
/// <summary>
/// Triggered when a region is backed up/persisted to storage
/// </summary>
/// <remarks>
/// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.Backup"/>
/// and is fired before the persistence occurs.
/// </remarks>
public event OnBackupDelegate OnBackup; public event OnBackupDelegate OnBackup;
public delegate void OnClientConnectCoreDelegate(IClientCore client); public delegate void OnClientConnectCoreDelegate(IClientCore client);
/// <summary>
/// Triggered when a new client connects to the scene.
/// </summary>
/// <remarks>
/// This gets triggered in <see cref="TriggerOnNewClient"/>,
/// which checks if an instance of <see cref="OpenSim.Framework.IClientAPI"/>
/// also implements <see cref="OpenSim.Framework.Client.IClientCore"/> and as such,
/// is not triggered by <see cref="OpenSim.Region.OptionalModules.World.NPC">NPCs</see>.
/// </remarks>
public event OnClientConnectCoreDelegate OnClientConnect; public event OnClientConnectCoreDelegate OnClientConnect;
public delegate void OnNewClientDelegate(IClientAPI client); public delegate void OnNewClientDelegate(IClientAPI client);
@ -87,22 +132,74 @@ namespace OpenSim.Region.Framework.Scenes
public delegate void OnNewPresenceDelegate(ScenePresence presence); public delegate void OnNewPresenceDelegate(ScenePresence presence);
/// <summary>
/// Triggered when a new presence is added to the scene
/// </summary>
/// <remarks>
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both
/// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
/// </remarks>
public event OnNewPresenceDelegate OnNewPresence; public event OnNewPresenceDelegate OnNewPresence;
public delegate void OnRemovePresenceDelegate(UUID agentId); public delegate void OnRemovePresenceDelegate(UUID agentId);
/// <summary>
/// Triggered when a presence is removed from the scene
/// </summary>
/// <remarks>
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both
/// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
/// </remarks>
public event OnRemovePresenceDelegate OnRemovePresence; public event OnRemovePresenceDelegate OnRemovePresence;
public delegate void OnParcelPrimCountUpdateDelegate(); public delegate void OnParcelPrimCountUpdateDelegate();
/// <summary>
/// Triggered whenever the prim count may have been altered, or prior
/// to an action that requires the current prim count to be accurate.
/// </summary>
/// <remarks>
/// Triggered by <see cref="TriggerParcelPrimCountUpdate"/> in
/// <see cref="OpenSim.OpenSimBase.CreateRegion"/>,
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.EventManagerOnRequestParcelPrimCountUpdate"/>,
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ClientOnParcelObjectOwnerRequest"/>,
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.GetPrimsFree"/>,
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.UpdateLandSold"/>,
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.DeedToGroup"/>,
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.SendLandUpdateToClient"/>
/// </remarks>
public event OnParcelPrimCountUpdateDelegate OnParcelPrimCountUpdate; public event OnParcelPrimCountUpdateDelegate OnParcelPrimCountUpdate;
public delegate void OnParcelPrimCountAddDelegate(SceneObjectGroup obj); public delegate void OnParcelPrimCountAddDelegate(SceneObjectGroup obj);
/// <summary>
/// Triggered in response to <see cref="OnParcelPrimCountUpdate"/> for
/// objects that actually contribute to parcel prim count.
/// </summary>
/// <remarks>
/// Triggered by <see cref="TriggerParcelPrimCountAdd"/> in
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.EventManagerOnParcelPrimCountUpdate"/>
/// </remarks>
public event OnParcelPrimCountAddDelegate OnParcelPrimCountAdd; public event OnParcelPrimCountAddDelegate OnParcelPrimCountAdd;
public delegate void OnPluginConsoleDelegate(string[] args); public delegate void OnPluginConsoleDelegate(string[] args);
/// <summary>
/// Triggered after <see cref="OpenSim.IApplicationPlugin.PostInitialise"/>
/// has been called for all <see cref="OpenSim.IApplicationPlugin"/>
/// loaded via <see cref="OpenSim.OpenSimBase.LoadPlugins"/>.
/// Handlers for this event are typically used to parse the arguments
/// from <see cref="OnPluginConsoleDelegate"/> in order to process or
/// filter the arguments and pass them onto <see cref="OpenSim.Region.CoreModules.Framework.InterfaceCommander.Commander.ProcessConsoleCommand"/>
/// </summary>
/// <remarks>
/// Triggered by <see cref="TriggerOnPluginConsole"/> in
/// <see cref="Scene.SendCommandToPlugins"/> via
/// <see cref="SceneManager.SendCommandToPluginModules"/> via
/// <see cref="OpenSim.OpenSimBase.HandleCommanderCommand"/> via
/// <see cref="OpenSim.OpenSimBase.AddPluginCommands"/> via
/// <see cref="OpenSim.OpenSimBase.StartupSpecific"/>
/// </remarks>
public event OnPluginConsoleDelegate OnPluginConsole; public event OnPluginConsoleDelegate OnPluginConsole;
/// <summary> /// <summary>
@ -117,8 +214,28 @@ namespace OpenSim.Region.Framework.Scenes
public delegate void OnSetRootAgentSceneDelegate(UUID agentID, Scene scene); public delegate void OnSetRootAgentSceneDelegate(UUID agentID, Scene scene);
/// <summary>
/// Triggered before the grunt work for adding a root agent to a
/// scene has been performed (resuming attachment scripts, physics,
/// animations etc.)
/// </summary>
/// <remarks>
/// Triggered before <see cref="OnMakeRootAgent"/>
/// by <see cref="TriggerSetRootAgentScene"/>
/// in <see cref="ScenePresence.MakeRootAgent"/>
/// via <see cref="Scene.AgentCrossing"/>
/// and <see cref="ScenePresence.CompleteMovement"/>
/// </remarks>
public event OnSetRootAgentSceneDelegate OnSetRootAgentScene; public event OnSetRootAgentSceneDelegate OnSetRootAgentScene;
/// <summary>
/// Triggered after parcel properties have been updated.
/// </summary>
/// <remarks>
/// Triggered by <see cref="TriggerOnParcelPropertiesUpdateRequest"/> in
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ClientOnParcelPropertiesUpdateRequest"/>,
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ProcessPropertiesUpdate"/>
/// </remarks>
public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
/// <summary> /// <summary>
@ -133,12 +250,34 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Fired when an object is touched/grabbed. /// Fired when an object is touched/grabbed.
/// </summary> /// </summary>
/// <remarks>
/// The originalID is the local ID of the part that was actually touched. The localID itself is always that of /// The originalID is the local ID of the part that was actually touched. The localID itself is always that of
/// the root part. /// the root part.
/// Triggerd in response to <see cref="OpenSim.Framework.IClientAPI.OnGrabObject"/>
/// via <see cref="TriggerObjectGrab"/>
/// in <see cref="Scene.ProcessObjectGrab"/>
/// </remarks>
public event ObjectGrabDelegate OnObjectGrab; public event ObjectGrabDelegate OnObjectGrab;
public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs); public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs);
/// <summary>
/// Triggered when an object is being touched/grabbed continuously.
/// </summary>
/// <remarks>
/// Triggered in response to <see cref="OpenSim.Framework.IClientAPI.OnGrabUpdate"/>
/// via <see cref="TriggerObjectGrabbing"/>
/// in <see cref="Scene.ProcessObjectGrabUpdate"/>
/// </remarks>
public event ObjectGrabDelegate OnObjectGrabbing; public event ObjectGrabDelegate OnObjectGrabbing;
/// <summary>
/// Triggered when an object stops being touched/grabbed.
/// </summary>
/// <remarks>
/// Triggered in response to <see cref="OpenSim.Framework.IClientAPI.OnDeGrabObject"/>
/// via <see cref="TriggerObjectDeGrab"/>
/// in <see cref="Scene.ProcessObjectDeGrab"/>
/// </remarks>
public event ObjectDeGrabDelegate OnObjectDeGrab; public event ObjectDeGrabDelegate OnObjectDeGrab;
public event ScriptResetDelegate OnScriptReset; public event ScriptResetDelegate OnScriptReset;
@ -299,15 +438,36 @@ namespace OpenSim.Region.Framework.Scenes
public event ScriptColliding OnScriptLandColliderEnd; public event ScriptColliding OnScriptLandColliderEnd;
public delegate void OnMakeChildAgentDelegate(ScenePresence presence); public delegate void OnMakeChildAgentDelegate(ScenePresence presence);
/// <summary>
/// Triggered when an agent has been made a child agent of a scene.
/// </summary>
/// <remarks>
/// Triggered by <see cref="TriggerOnMakeChildAgent"/>
/// in <see cref="ScenePresence.MakeChildAgent"/>
/// via <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.CrossAgentToNewRegionAsync"/>,
/// <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.DoTeleport"/>,
/// <see cref="OpenSim.Region.CoreModules.InterGrid.KillAUser.ShutdownNoLogout"/>
/// </remarks>
public event OnMakeChildAgentDelegate OnMakeChildAgent; public event OnMakeChildAgentDelegate OnMakeChildAgent;
public delegate void OnSaveNewWindlightProfileDelegate(); public delegate void OnSaveNewWindlightProfileDelegate();
public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionLightShareData wl, UUID user); public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionLightShareData wl, UUID user);
/// <summary> /// <summary>
/// Triggered after the grunt work for adding a root agent to a
/// scene has been performed (resuming attachment scripts, physics,
/// animations etc.)
/// </summary>
/// <remarks>
/// This event is on the critical path for transferring an avatar from one region to another. Try and do /// This event is on the critical path for transferring an avatar from one region to another. Try and do
/// as little work on this event as possible, or do work asynchronously. /// as little work on this event as possible, or do work asynchronously.
/// </summary> /// Triggered after <see cref="OnSetRootAgentScene"/>
/// by <see cref="TriggerOnMakeRootAgent"/>
/// in <see cref="ScenePresence.MakeRootAgent"/>
/// via <see cref="Scene.AgentCrossing"/>
/// and <see cref="ScenePresence.CompleteMovement"/>
/// </remarks>
public event Action<ScenePresence> OnMakeRootAgent; public event Action<ScenePresence> OnMakeRootAgent;
public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted; public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted;
@ -333,9 +493,10 @@ namespace OpenSim.Region.Framework.Scenes
public event AvatarKillData OnAvatarKilled; public event AvatarKillData OnAvatarKilled;
public delegate void AvatarKillData(uint KillerLocalID, ScenePresence avatar); public delegate void AvatarKillData(uint KillerLocalID, ScenePresence avatar);
// public delegate void ScriptTimerEvent(uint localID, double timerinterval); /*
public delegate void ScriptTimerEvent(uint localID, double timerinterval);
// public event ScriptTimerEvent OnScriptTimerEvent; public event ScriptTimerEvent OnScriptTimerEvent;
*/
public delegate void EstateToolsSunUpdate(ulong regionHandle, bool FixedTime, bool EstateSun, float LindenHour); public delegate void EstateToolsSunUpdate(ulong regionHandle, bool FixedTime, bool EstateSun, float LindenHour);
public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID); public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID);
@ -345,12 +506,27 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Triggered when an object is added to the scene. /// Triggered when an object is added to the scene.
/// </summary> /// </summary>
/// <remarks>
/// Triggered by <see cref="TriggerObjectAddedToScene"/>
/// in <see cref="Scene.AddNewSceneObject"/>,
/// <see cref="Scene.DuplicateObject"/>,
/// <see cref="Scene.doObjectDuplicateOnRay"/>
/// </remarks>
public event Action<SceneObjectGroup> OnObjectAddedToScene; public event Action<SceneObjectGroup> OnObjectAddedToScene;
/// <summary>
/// Delegate for <see cref="OnObjectBeingRemovedFromScene"/>
/// </summary>
/// <param name="obj">The object being removed from the scene</param>
public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj);
/// <summary> /// <summary>
/// Triggered when an object is removed from the scene. /// Triggered when an object is removed from the scene.
/// </summary> /// </summary>
public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj); /// <remarks>
/// Triggered by <see cref="TriggerObjectBeingRemovedFromScene"/>
/// in <see cref="Scene.DeleteSceneObject"/>
/// </remarks>
public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene; public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene;
public delegate void NoticeNoLandDataFromStorage(); public delegate void NoticeNoLandDataFromStorage();
@ -366,6 +542,20 @@ namespace OpenSim.Region.Framework.Scenes
public event RequestParcelPrimCountUpdate OnRequestParcelPrimCountUpdate; public event RequestParcelPrimCountUpdate OnRequestParcelPrimCountUpdate;
public delegate void ParcelPrimCountTainted(); public delegate void ParcelPrimCountTainted();
/// <summary>
/// Triggered when the parcel prim count has been altered.
/// </summary>
/// <remarks>
/// Triggered by <see cref="TriggerParcelPrimCountTainted"/> in
/// <see cref="OpenSim.Region.CoreModules.Avatar.Attachments.AttachmentsModule.DetachSingleAttachmentToGround"/>,
/// <see cref="OpenSim.Region.CoreModules.Avatar.Attachments.AttachmentsModule.AttachToAgent"/>,
/// <see cref="Scene.DeleteSceneObject"/>,
/// <see cref="Scene.SelectPrim"/>,
/// <see cref="Scene.DeselectPrim"/>,
/// <see cref="SceneObjectGroup.UpdatePrimFlags"/>,
/// <see cref="SceneObjectGroup.AbsolutePosition"/>
/// </remarks>
public event ParcelPrimCountTainted OnParcelPrimCountTainted; public event ParcelPrimCountTainted OnParcelPrimCountTainted;
public event GetScriptRunning OnGetScriptRunning; public event GetScriptRunning OnGetScriptRunning;
@ -478,6 +668,9 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="copy"></param> /// <param name="copy"></param>
/// <param name="original"></param> /// <param name="original"></param>
/// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param> /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
/// <remarks>
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.SceneObjectPart.Copy"/>
/// </remarks>
public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy; public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy;
public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed); public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed);
@ -519,9 +712,28 @@ namespace OpenSim.Region.Framework.Scenes
public event PrimsLoaded OnPrimsLoaded; public event PrimsLoaded OnPrimsLoaded;
public delegate void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout); public delegate void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout);
/// <summary>
/// Triggered when a teleport starts
/// </summary>
/// <remarks>
/// Triggered by <see cref="TriggerTeleportStart"/>
/// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.CreateAgent"/>
/// and <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.HGEntityTransferModule.CreateAgent"/>
/// via <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.DoTeleport"/>
/// </remarks>
public event TeleportStart OnTeleportStart; public event TeleportStart OnTeleportStart;
public delegate void TeleportFail(IClientAPI client, bool gridLogout); public delegate void TeleportFail(IClientAPI client, bool gridLogout);
/// <summary>
/// Trigered when a teleport fails.
/// </summary>
/// <remarks>
/// Triggered by <see cref="TriggerTeleportFail"/>
/// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.Fail"/>
/// via <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.DoTeleport"/>
/// </remarks>
public event TeleportFail OnTeleportFail; public event TeleportFail OnTeleportFail;
public class MoneyTransferArgs : EventArgs public class MoneyTransferArgs : EventArgs
@ -529,7 +741,9 @@ namespace OpenSim.Region.Framework.Scenes
public UUID sender; public UUID sender;
public UUID receiver; public UUID receiver;
// Always false. The SL protocol sucks. /// <summary>
/// Always false. The SL protocol sucks.
/// </summary>
public bool authenticated = false; public bool authenticated = false;
public int amount; public int amount;

View File

@ -93,7 +93,7 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
public void StartScripts() public void StartScripts()
{ {
m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName); // m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName);
IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>(); IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>();
@ -1802,8 +1802,11 @@ namespace OpenSim.Region.Framework.Scenes
/// Rez a script into a prim's inventory from another prim /// Rez a script into a prim's inventory from another prim
/// </summary> /// </summary>
/// <param name="remoteClient"></param> /// <param name="remoteClient"></param>
/// <param name="itemID"> </param> /// <param name="srcPart"> </param>
/// <param name="localID"></param> /// <param name="destId"> </param>
/// <param name="pin"></param>
/// <param name="running"></param>
/// <param name="start_param"></param>
public void RezScriptFromPrim(UUID srcId, SceneObjectPart srcPart, UUID destId, int pin, int running, int start_param) public void RezScriptFromPrim(UUID srcId, SceneObjectPart srcPart, UUID destId, int pin, int running, int start_param)
{ {
TaskInventoryItem srcTaskItem = srcPart.Inventory.GetInventoryItem(srcId); TaskInventoryItem srcTaskItem = srcPart.Inventory.GetInventoryItem(srcId);
@ -1823,9 +1826,8 @@ namespace OpenSim.Region.Framework.Scenes
if (destPart == null) if (destPart == null)
{ {
m_log.ErrorFormat( m_log.ErrorFormat(
"[PRIM INVENTORY]: " + "[PRIM INVENTORY]: Could not find part {0} to insert script item {1} from {2} {3} in {4}",
"Could not find script for ID {0}", destId, srcId, srcPart.Name, srcPart.UUID, Name);
destId);
return; return;
} }
@ -1836,12 +1838,14 @@ namespace OpenSim.Region.Framework.Scenes
if ((destPart.GroupID == UUID.Zero) || (destPart.GroupID != srcPart.GroupID) || if ((destPart.GroupID == UUID.Zero) || (destPart.GroupID != srcPart.GroupID) ||
((destPart.GroupMask & (uint)PermissionMask.Modify) == 0)) ((destPart.GroupMask & (uint)PermissionMask.Modify) == 0))
return; return;
} else { }
else
{
if ((destPart.OwnerMask & (uint)PermissionMask.Modify) == 0) if ((destPart.OwnerMask & (uint)PermissionMask.Modify) == 0)
return; return;
} }
if (destPart.ScriptAccessPin != pin) if (destPart.ScriptAccessPin == 0 || destPart.ScriptAccessPin != pin)
{ {
m_log.WarnFormat( m_log.WarnFormat(
"[PRIM INVENTORY]: " + "[PRIM INVENTORY]: " +

View File

@ -468,7 +468,7 @@ namespace OpenSim.Region.Framework.Scenes
if (!InventoryService.AddFolder(folder)) if (!InventoryService.AddFolder(folder))
{ {
m_log.WarnFormat( m_log.WarnFormat(
"[AGENT INVENTORY]: Failed to move create folder for user {0} {1}", "[AGENT INVENTORY]: Failed to create folder for user {0} {1}",
remoteClient.Name, remoteClient.AgentId); remoteClient.Name, remoteClient.AgentId);
} }
} }

View File

@ -128,7 +128,8 @@ namespace OpenSim.Region.Framework.Scenes
// TODO: need to figure out how allow client agents but deny // TODO: need to figure out how allow client agents but deny
// root agents when ACL denies access to root agent // root agents when ACL denies access to root agent
public bool m_strictAccessControl = true; public bool m_strictAccessControl = true;
public int MaxUndoCount = 5;
public int MaxUndoCount { get; set; }
// Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
public bool LoginLock = false; public bool LoginLock = false;
@ -714,6 +715,8 @@ namespace OpenSim.Region.Framework.Scenes
//Animation states //Animation states
m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20);
PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims);
CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims); CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims);
@ -817,6 +820,8 @@ namespace OpenSim.Region.Framework.Scenes
} }
// FIXME: Ultimately this should be in a module. // FIXME: Ultimately this should be in a module.
SendPeriodicAppearanceUpdates = true;
IConfig appearanceConfig = m_config.Configs["Appearance"]; IConfig appearanceConfig = m_config.Configs["Appearance"];
if (appearanceConfig != null) if (appearanceConfig != null)
{ {
@ -3529,7 +3534,7 @@ namespace OpenSim.Region.Framework.Scenes
"[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
sp.Name, sp.UUID, RegionInfo.RegionName); sp.Name, sp.UUID, RegionInfo.RegionName);
sp.ControllingClient.Close(); sp.ControllingClient.Close(true);
sp = null; sp = null;
} }
@ -4083,16 +4088,19 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Tell a single agent to disconnect from the region. /// Tell a single agent to disconnect from the region.
/// </summary> /// </summary>
/// <param name="regionHandle"></param>
/// <param name="agentID"></param> /// <param name="agentID"></param>
public bool IncomingCloseAgent(UUID agentID) /// <param name="force">
/// Force the agent to close even if it might be in the middle of some other operation. You do not want to
/// force unless you are absolutely sure that the agent is dead and a normal close is not working.
/// </param>
public bool IncomingCloseAgent(UUID agentID, bool force)
{ {
//m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); ScenePresence presence = m_sceneGraph.GetScenePresence(agentID);
if (presence != null) if (presence != null)
{ {
presence.ControllingClient.Close(); presence.ControllingClient.Close(force);
return true; return true;
} }

View File

@ -300,7 +300,7 @@ namespace OpenSim.Region.Framework.Scenes
public bool AddNewSceneObject( public bool AddNewSceneObject(
SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel)
{ {
AddNewSceneObject(sceneObject, true, false); AddNewSceneObject(sceneObject, attachToBackup, false);
if (pos != null) if (pos != null)
sceneObject.AbsolutePosition = (Vector3)pos; sceneObject.AbsolutePosition = (Vector3)pos;

View File

@ -1119,14 +1119,6 @@ namespace OpenSim.Region.Framework.Scenes
parts[i].UUID = UUID.Random(); parts[i].UUID = UUID.Random();
} }
// helper provided for parts.
public int GetSceneMaxUndo()
{
if (m_scene != null)
return m_scene.MaxUndoCount;
return 5;
}
// justincc: I don't believe this hack is needed any longer, especially since the physics // justincc: I don't believe this hack is needed any longer, especially since the physics
// parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false
// this method was preventing proper reload of scene objects. // this method was preventing proper reload of scene objects.
@ -2674,27 +2666,23 @@ namespace OpenSim.Region.Framework.Scenes
RootPart.StoreUndoState(true); RootPart.StoreUndoState(true);
scale.X = Math.Min(scale.X, Scene.m_maxNonphys); if (Scene != null)
scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys);
scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys);
PhysicsActor pa = m_rootPart.PhysActor;
if (pa != null && pa.IsPhysical)
{ {
scale.X = Math.Min(scale.X, Scene.m_maxPhys); scale.X = Math.Min(scale.X, Scene.m_maxPhys);
scale.Y = Math.Min(scale.Y, Scene.m_maxPhys); scale.Y = Math.Min(scale.Y, Scene.m_maxPhys);
scale.Z = Math.Min(scale.Z, Scene.m_maxPhys); scale.Z = Math.Min(scale.Z, Scene.m_maxPhys);
} }
PhysicsActor pa = m_rootPart.PhysActor;
float x = (scale.X / RootPart.Scale.X); float x = (scale.X / RootPart.Scale.X);
float y = (scale.Y / RootPart.Scale.Y); float y = (scale.Y / RootPart.Scale.Y);
float z = (scale.Z / RootPart.Scale.Z); float z = (scale.Z / RootPart.Scale.Z);
SceneObjectPart[] parts; SceneObjectPart[] parts = m_parts.GetArray();
if (x > 1.0f || y > 1.0f || z > 1.0f)
if (Scene != null & (x > 1.0f || y > 1.0f || z > 1.0f))
{ {
parts = m_parts.GetArray();
for (int i = 0; i < parts.Length; i++) for (int i = 0; i < parts.Length; i++)
{ {
SceneObjectPart obPart = parts[i]; SceneObjectPart obPart = parts[i];
@ -2708,7 +2696,7 @@ namespace OpenSim.Region.Framework.Scenes
if (pa != null && pa.IsPhysical) if (pa != null && pa.IsPhysical)
{ {
if (oldSize.X * x > m_scene.m_maxPhys) if (oldSize.X * x > Scene.m_maxPhys)
{ {
f = m_scene.m_maxPhys / oldSize.X; f = m_scene.m_maxPhys / oldSize.X;
a = f / x; a = f / x;
@ -2717,7 +2705,7 @@ namespace OpenSim.Region.Framework.Scenes
z *= a; z *= a;
} }
if (oldSize.Y * y > m_scene.m_maxPhys) if (oldSize.Y * y > Scene.m_maxPhys)
{ {
f = m_scene.m_maxPhys / oldSize.Y; f = m_scene.m_maxPhys / oldSize.Y;
a = f / y; a = f / y;
@ -2726,7 +2714,7 @@ namespace OpenSim.Region.Framework.Scenes
z *= a; z *= a;
} }
if (oldSize.Z * z > m_scene.m_maxPhys) if (oldSize.Z * z > Scene.m_maxPhys)
{ {
f = m_scene.m_maxPhys / oldSize.Z; f = m_scene.m_maxPhys / oldSize.Z;
a = f / z; a = f / z;
@ -2737,7 +2725,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
else else
{ {
if (oldSize.X * x > m_scene.m_maxNonphys) if (oldSize.X * x > Scene.m_maxNonphys)
{ {
f = m_scene.m_maxNonphys / oldSize.X; f = m_scene.m_maxNonphys / oldSize.X;
a = f / x; a = f / x;
@ -2746,7 +2734,7 @@ namespace OpenSim.Region.Framework.Scenes
z *= a; z *= a;
} }
if (oldSize.Y * y > m_scene.m_maxNonphys) if (oldSize.Y * y > Scene.m_maxNonphys)
{ {
f = m_scene.m_maxNonphys / oldSize.Y; f = m_scene.m_maxNonphys / oldSize.Y;
a = f / y; a = f / y;
@ -2755,7 +2743,7 @@ namespace OpenSim.Region.Framework.Scenes
z *= a; z *= a;
} }
if (oldSize.Z * z > m_scene.m_maxNonphys) if (oldSize.Z * z > Scene.m_maxNonphys)
{ {
f = m_scene.m_maxNonphys / oldSize.Z; f = m_scene.m_maxNonphys / oldSize.Z;
a = f / z; a = f / z;
@ -2779,7 +2767,6 @@ namespace OpenSim.Region.Framework.Scenes
RootPart.Resize(prevScale); RootPart.Resize(prevScale);
// RootPart.IgnoreUndoUpdate = false; // RootPart.IgnoreUndoUpdate = false;
parts = m_parts.GetArray();
for (int i = 0; i < parts.Length; i++) for (int i = 0; i < parts.Length; i++)
{ {
SceneObjectPart obPart = parts[i]; SceneObjectPart obPart = parts[i];

View File

@ -266,8 +266,8 @@ namespace OpenSim.Region.Framework.Scenes
private string m_sitAnimation = "SIT"; private string m_sitAnimation = "SIT";
private string m_text = String.Empty; private string m_text = String.Empty;
private string m_touchName = String.Empty; private string m_touchName = String.Empty;
private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); private readonly List<UndoState> m_undo = new List<UndoState>(5);
private readonly Stack<UndoState> m_redo = new Stack<UndoState>(5); private readonly List<UndoState> m_redo = new List<UndoState>(5);
private bool m_passTouches = false; private bool m_passTouches = false;
private bool m_passCollisions = false; private bool m_passCollisions = false;
@ -733,7 +733,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
catch (Exception e) catch (Exception e)
{ {
m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e);
} }
} }
@ -2367,6 +2367,8 @@ namespace OpenSim.Region.Framework.Scenes
/// </remarks> /// </remarks>
/// <param name="scale"></param> /// <param name="scale"></param>
public void Resize(Vector3 scale) public void Resize(Vector3 scale)
{
if (ParentGroup.Scene != null)
{ {
scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxNonphys); scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxNonphys);
scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys); scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys);
@ -2380,6 +2382,7 @@ namespace OpenSim.Region.Framework.Scenes
scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys); scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys);
scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxPhys); scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxPhys);
} }
}
// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); // m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale);
@ -3150,61 +3153,62 @@ namespace OpenSim.Region.Framework.Scenes
public void StoreUndoState(bool forGroup) public void StoreUndoState(bool forGroup)
{ {
if (!Undoing) if (ParentGroup == null || ParentGroup.Scene == null)
return;
if (Undoing)
{ {
if (!IgnoreUndoUpdate) // m_log.DebugFormat(
{ // "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
if (ParentGroup != null) return;
}
if (IgnoreUndoUpdate)
{ {
// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
return;
}
lock (m_undo) lock (m_undo)
{ {
if (m_undo.Count > 0) if (m_undo.Count > 0)
{ {
UndoState last = m_undo.Peek(); UndoState last = m_undo[m_undo.Count - 1];
if (last != null) if (last != null)
{ {
// TODO: May need to fix for group comparison // TODO: May need to fix for group comparison
if (last.Compare(this)) if (last.Compare(this))
{ {
// m_log.DebugFormat( // m_log.DebugFormat(
// "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}", // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
// Name, LocalId, m_undo.Count); // Name, LocalId, m_undo.Count);
return; return;
} }
} }
} }
// m_log.DebugFormat( // m_log.DebugFormat(
// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}", // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
// Name, LocalId, forGroup, m_undo.Count); // Name, LocalId, forGroup, m_undo.Count);
if (ParentGroup.GetSceneMaxUndo() > 0) if (ParentGroup.Scene.MaxUndoCount > 0)
{ {
UndoState nUndo = new UndoState(this, forGroup); UndoState nUndo = new UndoState(this, forGroup);
m_undo.Push(nUndo); m_undo.Add(nUndo);
if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
m_undo.RemoveAt(0);
if (m_redo.Count > 0) if (m_redo.Count > 0)
m_redo.Clear(); m_redo.Clear();
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
// Name, LocalId, forGroup, m_undo.Count);
}
}
}
}
// else
// {
// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
// }
}
// else
// {
// m_log.DebugFormat( // m_log.DebugFormat(
// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
// } // Name, LocalId, forGroup, m_undo.Count);
}
}
} }
/// <summary> /// <summary>
@ -3229,13 +3233,12 @@ namespace OpenSim.Region.Framework.Scenes
if (m_undo.Count > 0) if (m_undo.Count > 0)
{ {
UndoState goback = m_undo.Pop(); UndoState goback = m_undo[m_undo.Count - 1];
m_undo.RemoveAt(m_undo.Count - 1);
if (goback != null)
{
UndoState nUndo = null; UndoState nUndo = null;
if (ParentGroup.GetSceneMaxUndo() > 0) if (ParentGroup.Scene.MaxUndoCount > 0)
{ {
nUndo = new UndoState(this, goback.ForGroup); nUndo = new UndoState(this, goback.ForGroup);
} }
@ -3243,7 +3246,11 @@ namespace OpenSim.Region.Framework.Scenes
goback.PlaybackState(this); goback.PlaybackState(this);
if (nUndo != null) if (nUndo != null)
m_redo.Push(nUndo); {
m_redo.Add(nUndo);
if (m_redo.Count > ParentGroup.Scene.MaxUndoCount)
m_redo.RemoveAt(0);
} }
} }
@ -3263,19 +3270,20 @@ namespace OpenSim.Region.Framework.Scenes
if (m_redo.Count > 0) if (m_redo.Count > 0)
{ {
UndoState gofwd = m_redo.Pop(); UndoState gofwd = m_redo[m_redo.Count - 1];
m_redo.RemoveAt(m_redo.Count - 1);
if (gofwd != null) if (ParentGroup.Scene.MaxUndoCount > 0)
{
if (ParentGroup.GetSceneMaxUndo() > 0)
{ {
UndoState nUndo = new UndoState(this, gofwd.ForGroup); UndoState nUndo = new UndoState(this, gofwd.ForGroup);
m_undo.Push(nUndo); m_undo.Add(nUndo);
if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
m_undo.RemoveAt(0);
} }
gofwd.PlayfwdState(this); gofwd.PlayfwdState(this);
}
// m_log.DebugFormat( // m_log.DebugFormat(
// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", // "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}",

View File

@ -891,7 +891,9 @@ namespace OpenSim.Region.Framework.Scenes
{ {
if (wasChild && HasAttachments()) if (wasChild && HasAttachments())
{ {
m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); m_log.DebugFormat(
"[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
// Resume scripts // Resume scripts
foreach (SceneObjectGroup sog in m_attachments) foreach (SceneObjectGroup sog in m_attachments)
{ {

View File

@ -62,8 +62,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
Assert.That(g1Post.RootPart.Scale.X, Is.EqualTo(2)); Assert.That(g1Post.RootPart.Scale.X, Is.EqualTo(2));
Assert.That(g1Post.RootPart.Scale.Y, Is.EqualTo(3)); Assert.That(g1Post.RootPart.Scale.Y, Is.EqualTo(3));
Assert.That(g1Post.RootPart.Scale.Z, Is.EqualTo(4)); Assert.That(g1Post.RootPart.Scale.Z, Is.EqualTo(4));
Assert.That(g1Post.RootPart.UndoCount, Is.EqualTo(1));
} }
/// <summary> /// <summary>

View File

@ -0,0 +1,184 @@
/*
* 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 NUnit.Framework;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Communications;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock;
namespace OpenSim.Region.Framework.Scenes.Tests
{
/// <summary>
/// Tests for undo/redo
/// </summary>
public class SceneObjectUndoRedoTests : OpenSimTestCase
{
[Test]
public void TestUndoRedoResizeSceneObject()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
Vector3 firstSize = new Vector3(2, 3, 4);
Vector3 secondSize = new Vector3(5, 6, 7);
Scene scene = new SceneHelpers().SetupScene();
scene.MaxUndoCount = 20;
SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene);
// TODO: It happens to be the case that we are not storing undo states for SOPs which are not yet in a SOG,
// which is the way that AddSceneObject() sets up the object (i.e. it creates the SOP first). However,
// this is somewhat by chance. Really, we shouldn't be storing undo states at all if the object is not
// in a scene.
Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0));
g1.GroupResize(firstSize);
Assert.That(g1.RootPart.UndoCount, Is.EqualTo(1));
g1.GroupResize(secondSize);
Assert.That(g1.RootPart.UndoCount, Is.EqualTo(2));
g1.RootPart.Undo();
Assert.That(g1.RootPart.UndoCount, Is.EqualTo(1));
Assert.That(g1.GroupScale, Is.EqualTo(firstSize));
g1.RootPart.Redo();
Assert.That(g1.RootPart.UndoCount, Is.EqualTo(2));
Assert.That(g1.GroupScale, Is.EqualTo(secondSize));
}
[Test]
public void TestUndoLimit()
{
TestHelpers.InMethod();
Vector3 firstSize = new Vector3(2, 3, 4);
Vector3 secondSize = new Vector3(5, 6, 7);
Vector3 thirdSize = new Vector3(8, 9, 10);
Vector3 fourthSize = new Vector3(11, 12, 13);
Scene scene = new SceneHelpers().SetupScene();
scene.MaxUndoCount = 2;
SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene);
g1.GroupResize(firstSize);
g1.GroupResize(secondSize);
g1.GroupResize(thirdSize);
g1.GroupResize(fourthSize);
g1.RootPart.Undo();
g1.RootPart.Undo();
g1.RootPart.Undo();
Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0));
Assert.That(g1.GroupScale, Is.EqualTo(secondSize));
}
[Test]
public void TestNoUndoOnObjectsNotInScene()
{
TestHelpers.InMethod();
Vector3 firstSize = new Vector3(2, 3, 4);
Vector3 secondSize = new Vector3(5, 6, 7);
Vector3 thirdSize = new Vector3(8, 9, 10);
Vector3 fourthSize = new Vector3(11, 12, 13);
Scene scene = new SceneHelpers().SetupScene();
scene.MaxUndoCount = 20;
SceneObjectGroup g1 = SceneHelpers.CreateSceneObject(1, TestHelpers.ParseTail(0x1));
g1.GroupResize(firstSize);
g1.GroupResize(secondSize);
Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0));
g1.RootPart.Undo();
Assert.That(g1.GroupScale, Is.EqualTo(secondSize));
}
[Test]
public void TestUndoBeyondAvailable()
{
TestHelpers.InMethod();
Vector3 newSize = new Vector3(2, 3, 4);
Scene scene = new SceneHelpers().SetupScene();
scene.MaxUndoCount = 20;
SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene);
Vector3 originalSize = g1.GroupScale;
g1.RootPart.Undo();
Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0));
Assert.That(g1.GroupScale, Is.EqualTo(originalSize));
g1.GroupResize(newSize);
Assert.That(g1.RootPart.UndoCount, Is.EqualTo(1));
Assert.That(g1.GroupScale, Is.EqualTo(newSize));
g1.RootPart.Undo();
g1.RootPart.Undo();
Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0));
Assert.That(g1.GroupScale, Is.EqualTo(originalSize));
}
[Test]
public void TestRedoBeyondAvailable()
{
TestHelpers.InMethod();
Vector3 newSize = new Vector3(2, 3, 4);
Scene scene = new SceneHelpers().SetupScene();
scene.MaxUndoCount = 20;
SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene);
Vector3 originalSize = g1.GroupScale;
g1.RootPart.Redo();
Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0));
Assert.That(g1.GroupScale, Is.EqualTo(originalSize));
g1.GroupResize(newSize);
g1.RootPart.Undo();
g1.RootPart.Redo();
g1.RootPart.Redo();
Assert.That(g1.RootPart.UndoCount, Is.EqualTo(1));
Assert.That(g1.GroupScale, Is.EqualTo(newSize));
}
}
}

View File

@ -44,7 +44,7 @@ using OpenSim.Tests.Common.Mock;
namespace OpenSim.Region.Framework.Scenes.Tests namespace OpenSim.Region.Framework.Scenes.Tests
{ {
[TestFixture] [TestFixture]
public class SceneObjectUserGroupTests public class SceneObjectUserGroupTests : OpenSimTestCase
{ {
/// <summary> /// <summary>
/// Test share with group object functionality /// Test share with group object functionality
@ -54,7 +54,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
public void TestShareWithGroup() public void TestShareWithGroup()
{ {
TestHelpers.InMethod(); TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure();
UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001");

View File

@ -141,7 +141,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
TestScene scene = new SceneHelpers().SetupScene(); TestScene scene = new SceneHelpers().SetupScene();
ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
scene.IncomingCloseAgent(sp.UUID); scene.IncomingCloseAgent(sp.UUID, false);
Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); Assert.That(scene.GetScenePresence(sp.UUID), Is.Null);
Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null);

View File

@ -50,8 +50,40 @@ using OpenSim.Tests.Common.Mock;
namespace OpenSim.Region.Framework.Tests namespace OpenSim.Region.Framework.Tests
{ {
[TestFixture] [TestFixture]
public class UserInventoryTests public class UserInventoryTests : OpenSimTestCase
{ {
[Test]
public void TestCreateInventoryFolders()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
// For this test both folders will have the same name which is legal in SL user inventories.
string foldersName = "f1";
Scene scene = new SceneHelpers().SetupScene();
UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));
UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName);
List<InventoryFolderBase> oneFolder
= UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName);
Assert.That(oneFolder.Count, Is.EqualTo(1));
InventoryFolderBase firstRetrievedFolder = oneFolder[0];
Assert.That(firstRetrievedFolder.Name, Is.EqualTo(foldersName));
UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName);
List<InventoryFolderBase> twoFolders
= UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName);
Assert.That(twoFolders.Count, Is.EqualTo(2));
Assert.That(twoFolders[0].Name, Is.EqualTo(foldersName));
Assert.That(twoFolders[1].Name, Is.EqualTo(foldersName));
Assert.That(twoFolders[0].ID, Is.Not.EqualTo(twoFolders[1].ID));
}
[Test] [Test]
public void TestGiveInventoryItem() public void TestGiveInventoryItem()
{ {
@ -83,7 +115,7 @@ namespace OpenSim.Region.Framework.Tests
public void TestGiveInventoryFolder() public void TestGiveInventoryFolder()
{ {
TestHelpers.InMethod(); TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure(); // TestHelpers.EnableLogging();
Scene scene = new SceneHelpers().SetupScene(); Scene scene = new SceneHelpers().SetupScene();
UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));

View File

@ -885,6 +885,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
} }
public void Close() public void Close()
{
Close(false);
}
public void Close(bool force)
{ {
Disconnect(); Disconnect();
} }

View File

@ -231,12 +231,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
if (m_server == null || m_baseNick == null || m_ircChannel == null || m_user == null) if (m_server == null || m_baseNick == null || m_ircChannel == null || m_user == null)
throw new Exception("Invalid connector configuration"); throw new Exception("Invalid connector configuration");
// Generate an initial nickname if randomizing is enabled // Generate an initial nickname
if (m_randomizeNick) if (m_randomizeNick)
{
m_nick = m_baseNick + Util.RandomClass.Next(1, 99); m_nick = m_baseNick + Util.RandomClass.Next(1, 99);
} else
m_nick = m_baseNick;
m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn); m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn);

View File

@ -900,6 +900,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
} }
public void Close() public void Close()
{
Close(false);
}
public void Close(bool force)
{ {
// Remove ourselves from the scene // Remove ourselves from the scene
m_scene.RemoveClient(AgentId, false); m_scene.RemoveClient(AgentId, false);

View File

@ -176,8 +176,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
if (m_avatars.ContainsKey(agentID)) if (m_avatars.ContainsKey(agentID))
{ {
ScenePresence sp; ScenePresence sp;
scene.TryGetScenePresence(agentID, out sp); if (scene.TryGetScenePresence(agentID, out sp))
{
m_log.DebugFormat( m_log.DebugFormat(
"[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}", "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}",
sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget); sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget);
@ -188,6 +188,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
return true; return true;
} }
} }
}
return false; return false;
} }
@ -199,14 +200,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC
if (m_avatars.ContainsKey(agentID)) if (m_avatars.ContainsKey(agentID))
{ {
ScenePresence sp; ScenePresence sp;
scene.TryGetScenePresence(agentID, out sp); if (scene.TryGetScenePresence(agentID, out sp))
{
sp.Velocity = Vector3.Zero; sp.Velocity = Vector3.Zero;
sp.ResetMoveToTarget(); sp.ResetMoveToTarget();
return true; return true;
} }
} }
}
return false; return false;
} }
@ -222,9 +224,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{ {
if (m_avatars.ContainsKey(agentID)) if (m_avatars.ContainsKey(agentID))
{ {
ScenePresence sp;
scene.TryGetScenePresence(agentID, out sp);
m_avatars[agentID].Say(channel, text); m_avatars[agentID].Say(channel, text);
return true; return true;
@ -240,9 +239,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{ {
if (m_avatars.ContainsKey(agentID)) if (m_avatars.ContainsKey(agentID))
{ {
ScenePresence sp;
scene.TryGetScenePresence(agentID, out sp);
m_avatars[agentID].Shout(channel, text); m_avatars[agentID].Shout(channel, text);
return true; return true;
@ -259,13 +255,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC
if (m_avatars.ContainsKey(agentID)) if (m_avatars.ContainsKey(agentID))
{ {
ScenePresence sp; ScenePresence sp;
scene.TryGetScenePresence(agentID, out sp); if (scene.TryGetScenePresence(agentID, out sp))
{
sp.HandleAgentRequestSit(m_avatars[agentID], agentID, partID, Vector3.Zero); sp.HandleAgentRequestSit(m_avatars[agentID], agentID, partID, Vector3.Zero);
// sp.HandleAgentSit(m_avatars[agentID], agentID); // sp.HandleAgentSit(m_avatars[agentID], agentID);
return true; return true;
} }
} }
}
return false; return false;
} }
@ -276,9 +274,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{ {
if (m_avatars.ContainsKey(agentID)) if (m_avatars.ContainsKey(agentID))
{ {
ScenePresence sp;
scene.TryGetScenePresence(agentID, out sp);
m_avatars[agentID].Whisper(channel, text); m_avatars[agentID].Whisper(channel, text);
return true; return true;
@ -295,12 +290,14 @@ namespace OpenSim.Region.OptionalModules.World.NPC
if (m_avatars.ContainsKey(agentID)) if (m_avatars.ContainsKey(agentID))
{ {
ScenePresence sp; ScenePresence sp;
scene.TryGetScenePresence(agentID, out sp); if (scene.TryGetScenePresence(agentID, out sp))
{
sp.StandUp(); sp.StandUp();
return true; return true;
} }
} }
}
return false; return false;
} }
@ -311,6 +308,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{ {
if (m_avatars.ContainsKey(agentID)) if (m_avatars.ContainsKey(agentID))
return m_avatars[agentID].Touch(objectID); return m_avatars[agentID].Touch(objectID);
return false; return false;
} }
} }
@ -321,10 +319,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{ {
NPCAvatar av; NPCAvatar av;
if (m_avatars.TryGetValue(agentID, out av)) if (m_avatars.TryGetValue(agentID, out av))
{
return av.OwnerID; return av.OwnerID;
} }
}
return UUID.Zero; return UUID.Zero;
} }

View File

@ -183,6 +183,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void llResetScript() public void llResetScript()
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
// We need to tell the URL module, if we hav one, to release
// the allocated URLs
if (m_UrlModule != null)
m_UrlModule.ScriptRemoved(m_item.ItemID);
m_ScriptEngine.ApiResetScript(m_item.ItemID); m_ScriptEngine.ApiResetScript(m_item.ItemID);
} }
@ -237,33 +243,38 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
public List<SceneObjectPart> GetLinkParts(int linkType) public List<SceneObjectPart> GetLinkParts(int linkType)
{
return GetLinkParts(m_host, linkType);
}
private List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType)
{ {
List<SceneObjectPart> ret = new List<SceneObjectPart>(); List<SceneObjectPart> ret = new List<SceneObjectPart>();
ret.Add(m_host); ret.Add(part);
switch (linkType) switch (linkType)
{ {
case ScriptBaseClass.LINK_SET: case ScriptBaseClass.LINK_SET:
return new List<SceneObjectPart>(m_host.ParentGroup.Parts); return new List<SceneObjectPart>(part.ParentGroup.Parts);
case ScriptBaseClass.LINK_ROOT: case ScriptBaseClass.LINK_ROOT:
ret = new List<SceneObjectPart>(); ret = new List<SceneObjectPart>();
ret.Add(m_host.ParentGroup.RootPart); ret.Add(part.ParentGroup.RootPart);
return ret; return ret;
case ScriptBaseClass.LINK_ALL_OTHERS: case ScriptBaseClass.LINK_ALL_OTHERS:
ret = new List<SceneObjectPart>(m_host.ParentGroup.Parts); ret = new List<SceneObjectPart>(part.ParentGroup.Parts);
if (ret.Contains(m_host)) if (ret.Contains(part))
ret.Remove(m_host); ret.Remove(part);
return ret; return ret;
case ScriptBaseClass.LINK_ALL_CHILDREN: case ScriptBaseClass.LINK_ALL_CHILDREN:
ret = new List<SceneObjectPart>(m_host.ParentGroup.Parts); ret = new List<SceneObjectPart>(part.ParentGroup.Parts);
if (ret.Contains(m_host.ParentGroup.RootPart)) if (ret.Contains(part.ParentGroup.RootPart))
ret.Remove(m_host.ParentGroup.RootPart); ret.Remove(part.ParentGroup.RootPart);
return ret; return ret;
case ScriptBaseClass.LINK_THIS: case ScriptBaseClass.LINK_THIS:
@ -273,7 +284,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (linkType < 0) if (linkType < 0)
return new List<SceneObjectPart>(); return new List<SceneObjectPart>();
SceneObjectPart target = m_host.ParentGroup.GetLinkNumPart(linkType); SceneObjectPart target = part.ParentGroup.GetLinkNumPart(linkType);
if (target == null) if (target == null)
return new List<SceneObjectPart>(); return new List<SceneObjectPart>();
ret = new List<SceneObjectPart>(); ret = new List<SceneObjectPart>();
@ -5427,27 +5438,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
/// Returns the index of the first occurrence of test /// Returns the index of the first occurrence of test
/// in src. /// in src.
/// </summary> /// </summary>
/// <param name="src">Source list</param>
/// <param name="test">List to search for</param>
/// <returns>
/// The index number of the point in src where test was found if it was found.
/// Otherwise returns -1
/// </returns>
public LSL_Integer llListFindList(LSL_List src, LSL_List test) public LSL_Integer llListFindList(LSL_List src, LSL_List test)
{ {
int index = -1; int index = -1;
int length = src.Length - test.Length + 1; int length = src.Length - test.Length + 1;
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
// If either list is empty, do not match // If either list is empty, do not match
if (src.Length != 0 && test.Length != 0) if (src.Length != 0 && test.Length != 0)
{ {
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
{ {
if (src.Data[i].Equals(test.Data[0])) // Why this piece of insanity? This is because most script constants are C# value types (e.g. int)
// rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code
// and so the comparison fails even if the LSL_Integer conceptually has the same value.
// Therefore, here we test Equals on both the source and destination objects.
// However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)).
if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i]))
{ {
int j; int j;
for (j = 1; j < test.Length; j++) for (j = 1; j < test.Length; j++)
if (!src.Data[i+j].Equals(test.Data[j])) if (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j])))
break; break;
if (j == test.Length) if (j == test.Length)
{ {
index = i; index = i;
@ -5458,19 +5478,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
return index; return index;
} }
public LSL_String llGetObjectName() public LSL_String llGetObjectName()
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
return m_host.Name!=null?m_host.Name:String.Empty; return m_host.Name !=null ? m_host.Name : String.Empty;
} }
public void llSetObjectName(string name) public void llSetObjectName(string name)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
m_host.Name = name!=null?name:String.Empty; m_host.Name = name != null ? name : String.Empty;
} }
public LSL_String llGetDate() public LSL_String llGetDate()
@ -7178,7 +7197,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void llSetPrimitiveParams(LSL_List rules) public void llSetPrimitiveParams(LSL_List rules)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
SetPrimParams(m_host, rules);
setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules);
ScriptSleep(200); ScriptSleep(200);
} }
@ -7203,11 +7223,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
List<SceneObjectPart> parts = GetLinkParts(linknumber); List<SceneObjectPart> parts = GetLinkParts(linknumber);
LSL_List remaining = null;
foreach (SceneObjectPart part in parts) foreach (SceneObjectPart part in parts)
SetPrimParams(part, rules); remaining = SetPrimParams(part, rules);
while(remaining != null && remaining.Length > 2)
{
linknumber = remaining.GetLSLIntegerItem(0);
rules = remaining.GetSublist(1,-1);
parts = GetLinkParts(linknumber);
foreach (SceneObjectPart part in parts)
remaining = SetPrimParams(part, rules);
}
} }
protected void SetPrimParams(SceneObjectPart part, LSL_List rules) protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules)
{ {
int idx = 0; int idx = 0;
@ -7230,7 +7262,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_POSITION: case (int)ScriptBaseClass.PRIM_POSITION:
case (int)ScriptBaseClass.PRIM_POS_LOCAL: case (int)ScriptBaseClass.PRIM_POS_LOCAL:
if (remain < 1) if (remain < 1)
return; return null;
v=rules.GetVector3Item(idx++); v=rules.GetVector3Item(idx++);
positionChanged = true; positionChanged = true;
@ -7239,7 +7271,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
break; break;
case (int)ScriptBaseClass.PRIM_SIZE: case (int)ScriptBaseClass.PRIM_SIZE:
if (remain < 1) if (remain < 1)
return; return null;
v=rules.GetVector3Item(idx++); v=rules.GetVector3Item(idx++);
SetScale(part, v); SetScale(part, v);
@ -7247,7 +7279,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
break; break;
case (int)ScriptBaseClass.PRIM_ROTATION: case (int)ScriptBaseClass.PRIM_ROTATION:
if (remain < 1) if (remain < 1)
return; return null;
LSL_Rotation q = rules.GetQuaternionItem(idx++); LSL_Rotation q = rules.GetQuaternionItem(idx++);
// try to let this work as in SL... // try to let this work as in SL...
@ -7267,7 +7299,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE: case (int)ScriptBaseClass.PRIM_TYPE:
if (remain < 3) if (remain < 3)
return; return null;
code = (int)rules.GetLSLIntegerItem(idx++); code = (int)rules.GetLSLIntegerItem(idx++);
@ -7286,7 +7318,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
case (int)ScriptBaseClass.PRIM_TYPE_BOX: case (int)ScriptBaseClass.PRIM_TYPE_BOX:
if (remain < 6) if (remain < 6)
return; return null;
face = (int)rules.GetLSLIntegerItem(idx++); face = (int)rules.GetLSLIntegerItem(idx++);
v = rules.GetVector3Item(idx++); // cut v = rules.GetVector3Item(idx++); // cut
@ -7301,7 +7333,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
if (remain < 6) if (remain < 6)
return; return null;
face = (int)rules.GetLSLIntegerItem(idx++); // holeshape face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
v = rules.GetVector3Item(idx++); // cut v = rules.GetVector3Item(idx++); // cut
@ -7315,7 +7347,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE_PRISM: case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
if (remain < 6) if (remain < 6)
return; return null;
face = (int)rules.GetLSLIntegerItem(idx++); // holeshape face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
v = rules.GetVector3Item(idx++); //cut v = rules.GetVector3Item(idx++); //cut
@ -7329,7 +7361,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
if (remain < 5) if (remain < 5)
return; return null;
face = (int)rules.GetLSLIntegerItem(idx++); // holeshape face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
v = rules.GetVector3Item(idx++); // cut v = rules.GetVector3Item(idx++); // cut
@ -7342,7 +7374,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE_TORUS: case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
if (remain < 11) if (remain < 11)
return; return null;
face = (int)rules.GetLSLIntegerItem(idx++); // holeshape face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
v = rules.GetVector3Item(idx++); //cut v = rules.GetVector3Item(idx++); //cut
@ -7361,7 +7393,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE_TUBE: case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
if (remain < 11) if (remain < 11)
return; return null;
face = (int)rules.GetLSLIntegerItem(idx++); // holeshape face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
v = rules.GetVector3Item(idx++); //cut v = rules.GetVector3Item(idx++); //cut
@ -7380,7 +7412,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE_RING: case (int)ScriptBaseClass.PRIM_TYPE_RING:
if (remain < 11) if (remain < 11)
return; return null;
face = (int)rules.GetLSLIntegerItem(idx++); // holeshape face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
v = rules.GetVector3Item(idx++); //cut v = rules.GetVector3Item(idx++); //cut
@ -7399,7 +7431,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
if (remain < 2) if (remain < 2)
return; return null;
string map = rules.Data[idx++].ToString(); string map = rules.Data[idx++].ToString();
face = (int)rules.GetLSLIntegerItem(idx++); // type face = (int)rules.GetLSLIntegerItem(idx++); // type
@ -7411,7 +7443,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TEXTURE: case (int)ScriptBaseClass.PRIM_TEXTURE:
if (remain < 5) if (remain < 5)
return; return null;
face=(int)rules.GetLSLIntegerItem(idx++); face=(int)rules.GetLSLIntegerItem(idx++);
string tex=rules.Data[idx++].ToString(); string tex=rules.Data[idx++].ToString();
@ -7428,7 +7460,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_COLOR: case (int)ScriptBaseClass.PRIM_COLOR:
if (remain < 3) if (remain < 3)
return; return null;
face=(int)rules.GetLSLIntegerItem(idx++); face=(int)rules.GetLSLIntegerItem(idx++);
LSL_Vector color=rules.GetVector3Item(idx++); LSL_Vector color=rules.GetVector3Item(idx++);
@ -7441,7 +7473,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_FLEXIBLE: case (int)ScriptBaseClass.PRIM_FLEXIBLE:
if (remain < 7) if (remain < 7)
return; return null;
bool flexi = rules.GetLSLIntegerItem(idx++); bool flexi = rules.GetLSLIntegerItem(idx++);
int softness = rules.GetLSLIntegerItem(idx++); int softness = rules.GetLSLIntegerItem(idx++);
@ -7457,7 +7489,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_POINT_LIGHT: case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
if (remain < 5) if (remain < 5)
return; return null;
bool light = rules.GetLSLIntegerItem(idx++); bool light = rules.GetLSLIntegerItem(idx++);
LSL_Vector lightcolor = rules.GetVector3Item(idx++); LSL_Vector lightcolor = rules.GetVector3Item(idx++);
float intensity = (float)rules.GetLSLFloatItem(idx++); float intensity = (float)rules.GetLSLFloatItem(idx++);
@ -7470,7 +7502,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_GLOW: case (int)ScriptBaseClass.PRIM_GLOW:
if (remain < 2) if (remain < 2)
return; return null;
face = rules.GetLSLIntegerItem(idx++); face = rules.GetLSLIntegerItem(idx++);
float glow = (float)rules.GetLSLFloatItem(idx++); float glow = (float)rules.GetLSLFloatItem(idx++);
@ -7480,7 +7512,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_BUMP_SHINY: case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
if (remain < 3) if (remain < 3)
return; return null;
face = (int)rules.GetLSLIntegerItem(idx++); face = (int)rules.GetLSLIntegerItem(idx++);
int shiny = (int)rules.GetLSLIntegerItem(idx++); int shiny = (int)rules.GetLSLIntegerItem(idx++);
Bumpiness bump = (Bumpiness)(int)rules.GetLSLIntegerItem(idx++); Bumpiness bump = (Bumpiness)(int)rules.GetLSLIntegerItem(idx++);
@ -7491,7 +7523,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_FULLBRIGHT: case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
if (remain < 2) if (remain < 2)
return; return null;
face = rules.GetLSLIntegerItem(idx++); face = rules.GetLSLIntegerItem(idx++);
bool st = rules.GetLSLIntegerItem(idx++); bool st = rules.GetLSLIntegerItem(idx++);
SetFullBright(part, face , st); SetFullBright(part, face , st);
@ -7499,17 +7531,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_MATERIAL: case (int)ScriptBaseClass.PRIM_MATERIAL:
if (remain < 1) if (remain < 1)
return; return null;
int mat = rules.GetLSLIntegerItem(idx++); int mat = rules.GetLSLIntegerItem(idx++);
if (mat < 0 || mat > 7) if (mat < 0 || mat > 7)
return; return null;
part.Material = Convert.ToByte(mat); part.Material = Convert.ToByte(mat);
break; break;
case (int)ScriptBaseClass.PRIM_PHANTOM: case (int)ScriptBaseClass.PRIM_PHANTOM:
if (remain < 1) if (remain < 1)
return; return null;
string ph = rules.Data[idx++].ToString(); string ph = rules.Data[idx++].ToString();
m_host.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1")); m_host.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1"));
@ -7518,7 +7550,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_PHYSICS: case (int)ScriptBaseClass.PRIM_PHYSICS:
if (remain < 1) if (remain < 1)
return; return null;
string phy = rules.Data[idx++].ToString(); string phy = rules.Data[idx++].ToString();
bool physics; bool physics;
@ -7532,7 +7564,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
if (remain < 1) if (remain < 1)
return; return null;
string temp = rules.Data[idx++].ToString(); string temp = rules.Data[idx++].ToString();
m_host.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1")); m_host.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1"));
@ -7541,7 +7573,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TEXGEN: case (int)ScriptBaseClass.PRIM_TEXGEN:
if (remain < 2) if (remain < 2)
return; return null;
//face,type //face,type
face = rules.GetLSLIntegerItem(idx++); face = rules.GetLSLIntegerItem(idx++);
int style = rules.GetLSLIntegerItem(idx++); int style = rules.GetLSLIntegerItem(idx++);
@ -7549,7 +7581,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
break; break;
case (int)ScriptBaseClass.PRIM_TEXT: case (int)ScriptBaseClass.PRIM_TEXT:
if (remain < 3) if (remain < 3)
return; return null;
string primText = rules.GetLSLStringItem(idx++); string primText = rules.GetLSLStringItem(idx++);
LSL_Vector primTextColor = rules.GetVector3Item(idx++); LSL_Vector primTextColor = rules.GetVector3Item(idx++);
LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++);
@ -7561,25 +7593,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
break; break;
case (int)ScriptBaseClass.PRIM_NAME: case (int)ScriptBaseClass.PRIM_NAME:
if (remain < 1) if (remain < 1)
return; return null;
string primName = rules.GetLSLStringItem(idx++); string primName = rules.GetLSLStringItem(idx++);
part.Name = primName; part.Name = primName;
break; break;
case (int)ScriptBaseClass.PRIM_DESC: case (int)ScriptBaseClass.PRIM_DESC:
if (remain < 1) if (remain < 1)
return; return null;
string primDesc = rules.GetLSLStringItem(idx++); string primDesc = rules.GetLSLStringItem(idx++);
part.Description = primDesc; part.Description = primDesc;
break; break;
case (int)ScriptBaseClass.PRIM_ROT_LOCAL: case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
if (remain < 1) if (remain < 1)
return; return null;
LSL_Rotation lr = rules.GetQuaternionItem(idx++); LSL_Rotation lr = rules.GetQuaternionItem(idx++);
SetRot(part, Rot2Quaternion(lr)); SetRot(part, Rot2Quaternion(lr));
break; break;
case (int)ScriptBaseClass.PRIM_OMEGA: case (int)ScriptBaseClass.PRIM_OMEGA:
if (remain < 3) if (remain < 3)
return; return null;
LSL_Vector axis = rules.GetVector3Item(idx++); LSL_Vector axis = rules.GetVector3Item(idx++);
LSL_Float spinrate = rules.GetLSLFloatItem(idx++); LSL_Float spinrate = rules.GetLSLFloatItem(idx++);
LSL_Float gain = rules.GetLSLFloatItem(idx++); LSL_Float gain = rules.GetLSLFloatItem(idx++);
@ -7587,12 +7619,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
break; break;
case (int)ScriptBaseClass.PRIM_LINK_TARGET: case (int)ScriptBaseClass.PRIM_LINK_TARGET:
if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
return; return null;
LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
LSL_List new_rules = rules.GetSublist(idx, -1);
setLinkPrimParams((int)new_linknumber, new_rules);
return; return rules.GetSublist(idx, -1);
} }
} }
} }
@ -7614,6 +7643,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
} }
} }
return null;
} }
public LSL_String llStringToBase64(string str) public LSL_String llStringToBase64(string str)
@ -10686,7 +10716,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (obj.OwnerID != m_host.OwnerID) if (obj.OwnerID != m_host.OwnerID)
return; return;
SetPrimParams(obj, rules); LSL_List remaining = SetPrimParams(obj, rules);
while (remaining != null && remaining.Length > 2)
{
LSL_Integer newLink = remaining.GetLSLIntegerItem(0);
LSL_List newrules = remaining.GetSublist(1, -1);
foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){
remaining = SetPrimParams(part, newrules);
}
}
} }
public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules) public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules)

View File

@ -2434,9 +2434,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (!npcModule.CheckPermissions(npcId, m_host.OwnerID)) if (!npcModule.CheckPermissions(npcId, m_host.OwnerID))
return new LSL_Vector(0, 0, 0); return new LSL_Vector(0, 0, 0);
Vector3 pos = World.GetScenePresence(npcId).AbsolutePosition; ScenePresence sp = World.GetScenePresence(npcId);
if (sp != null)
{
Vector3 pos = sp.AbsolutePosition;
return new LSL_Vector(pos.X, pos.Y, pos.Z); return new LSL_Vector(pos.X, pos.Y, pos.Z);
} }
}
return new LSL_Vector(0, 0, 0); return new LSL_Vector(0, 0, 0);
} }
@ -2503,10 +2508,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W); return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W);
ScenePresence sp = World.GetScenePresence(npcId); ScenePresence sp = World.GetScenePresence(npcId);
Quaternion rot = sp.Rotation;
if (sp != null)
{
Quaternion rot = sp.Rotation;
return new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W); return new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W);
} }
}
return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W); return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W);
} }
@ -2527,6 +2535,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return; return;
ScenePresence sp = World.GetScenePresence(npcId); ScenePresence sp = World.GetScenePresence(npcId);
if (sp != null)
sp.Rotation = LSL_Api.Rot2Quaternion(rotation); sp.Rotation = LSL_Api.Rot2Quaternion(rotation);
} }
} }
@ -2689,6 +2699,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
CheckThreatLevel(ThreatLevel.High, "osNpcTouch"); CheckThreatLevel(ThreatLevel.High, "osNpcTouch");
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
INPCModule module = World.RequestModuleInterface<INPCModule>(); INPCModule module = World.RequestModuleInterface<INPCModule>();
int linkNum = link_num.value; int linkNum = link_num.value;
if (module != null || (linkNum < 0 && linkNum != ScriptBaseClass.LINK_THIS)) if (module != null || (linkNum < 0 && linkNum != ScriptBaseClass.LINK_THIS))
@ -2696,12 +2707,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
UUID npcId; UUID npcId;
if (!UUID.TryParse(npcLSL_Key, out npcId) || !module.CheckPermissions(npcId, m_host.OwnerID)) if (!UUID.TryParse(npcLSL_Key, out npcId) || !module.CheckPermissions(npcId, m_host.OwnerID))
return; return;
SceneObjectPart part = null; SceneObjectPart part = null;
UUID objectId; UUID objectId;
if (UUID.TryParse(LSL_String.ToString(object_key), out objectId)) if (UUID.TryParse(LSL_String.ToString(object_key), out objectId))
part = World.GetSceneObjectPart(objectId); part = World.GetSceneObjectPart(objectId);
if (part == null) if (part == null)
return; return;
if (linkNum != ScriptBaseClass.LINK_THIS) if (linkNum != ScriptBaseClass.LINK_THIS)
{ {
if (linkNum == 0 || linkNum == ScriptBaseClass.LINK_ROOT) if (linkNum == 0 || linkNum == ScriptBaseClass.LINK_ROOT)
@ -2716,6 +2730,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return; return;
} }
} }
module.Touch(npcId, part.UUID); module.Touch(npcId, part.UUID);
} }
} }
@ -2866,7 +2881,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
avatar.SpeedModifier = (float)SpeedModifier; avatar.SpeedModifier = (float)SpeedModifier;
} }
public void osKickAvatar(string FirstName,string SurName,string alert) public void osKickAvatar(string FirstName, string SurName, string alert)
{ {
CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar"); CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar");
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
@ -2880,7 +2895,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
sp.ControllingClient.Kick(alert); sp.ControllingClient.Kick(alert);
// ...and close on our side // ...and close on our side
sp.Scene.IncomingCloseAgent(sp.UUID); sp.Scene.IncomingCloseAgent(sp.UUID, false);
} }
}); });
} }

View File

@ -40,16 +40,75 @@ using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
{ {
/// <summary>
/// To permit region owners to enable the extended scripting functionality
/// of OSSL, without allowing malicious scripts to access potentially
/// troublesome functions, each OSSL function is assigned a threat level,
/// and access to the functions is granted or denied based on a default
/// threshold set in OpenSim.ini (which can be overridden for individual
/// functions on a case-by-case basis)
/// </summary>
public enum ThreatLevel public enum ThreatLevel
{ {
// Not documented, presumably means permanently disabled ?
NoAccess = -1, NoAccess = -1,
/// <summary>
/// Function is no threat at all. It doesn't constitute a threat to
/// either users or the system and has no known side effects.
/// </summary>
None = 0, None = 0,
/// <summary>
/// Abuse of this command can cause a nuisance to the region operator,
/// such as log message spew.
/// </summary>
Nuisance = 1, Nuisance = 1,
/// <summary>
/// Extreme levels of abuse of this function can cause impaired
/// functioning of the region, or very gullible users can be tricked
/// into experiencing harmless effects.
/// </summary>
VeryLow = 2, VeryLow = 2,
/// <summary>
/// Intentional abuse can cause crashes or malfunction under certain
/// circumstances, which can be easily rectified; or certain users can
/// be tricked into certain situations in an avoidable manner.
/// </summary>
Low = 3, Low = 3,
/// <summary>
/// Intentional abuse can cause denial of service and crashes with
/// potential of data or state loss; or trusting users can be tricked
/// into embarrassing or uncomfortable situations.
/// </summary>
Moderate = 4, Moderate = 4,
/// <summary>
/// Casual abuse can cause impaired functionality or temporary denial
/// of service conditions. Intentional abuse can easily cause crashes
/// with potential data loss, or can be used to trick experienced and
/// cautious users into unwanted situations, or changes global data
/// permanently and without undo ability.
/// </summary>
High = 5, High = 5,
/// <summary>
/// Even normal use may, depending on the number of instances, or
/// frequency of use, result in severe service impairment or crash
/// with loss of data, or can be used to cause unwanted or harmful
/// effects on users without giving the user a means to avoid it.
/// </summary>
VeryHigh = 6, VeryHigh = 6,
/// <summary>
/// Even casual use is a danger to region stability, or function allows
/// console or OS command execution, or function allows taking money
/// without consent, or allows deletion or modification of user data,
/// or allows the compromise of sensitive data by design.
/// </summary>
Severe = 7 Severe = 7
}; };

View File

@ -226,6 +226,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
public const int ATTACH_BELLY = 28; public const int ATTACH_BELLY = 28;
public const int ATTACH_RPEC = 29; public const int ATTACH_RPEC = 29;
public const int ATTACH_LPEC = 30; public const int ATTACH_LPEC = 30;
public const int ATTACH_LEFT_PEC = 29; // Same value as ATTACH_RPEC, see https://jira.secondlife.com/browse/SVC-580
public const int ATTACH_RIGHT_PEC = 30; // Same value as ATTACH_LPEC, see https://jira.secondlife.com/browse/SVC-580
public const int ATTACH_HUD_CENTER_2 = 31; public const int ATTACH_HUD_CENTER_2 = 31;
public const int ATTACH_HUD_TOP_RIGHT = 32; public const int ATTACH_HUD_TOP_RIGHT = 32;
public const int ATTACH_HUD_TOP_CENTER = 33; public const int ATTACH_HUD_TOP_CENTER = 33;

View File

@ -1064,7 +1064,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
{ {
list ret = new list(); list ret = new list();
double entry; double entry;
for (int i = 0; i < src.Data.Length - 1; i++) for (int i = 0; i < src.Data.Length; i++)
{ {
if (double.TryParse(src.Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry)) if (double.TryParse(src.Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
{ {

View File

@ -164,5 +164,52 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
Assert.That(copiedItems[0].Name, Is.EqualTo(inventoryItemName)); Assert.That(copiedItems[0].Name, Is.EqualTo(inventoryItemName));
} }
} }
[Test]
public void TestLlRemoteLoadScriptPin()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
UUID user1Id = TestHelpers.ParseTail(0x1);
UUID user2Id = TestHelpers.ParseTail(0x2);
SceneObjectGroup sourceSo = SceneHelpers.AddSceneObject(m_scene, "sourceSo", user1Id);
m_scene.AddSceneObject(sourceSo);
LSL_Api api = new LSL_Api();
api.Initialize(m_engine, sourceSo.RootPart, null);
TaskInventoryHelpers.AddScript(m_scene, sourceSo.RootPart, "script", "Hello World");
SceneObjectGroup targetSo = SceneHelpers.AddSceneObject(m_scene, "targetSo", user1Id);
SceneObjectGroup otherOwnedTargetSo = SceneHelpers.AddSceneObject(m_scene, "otherOwnedTargetSo", user2Id);
// Test that we cannot load a script when the target pin has never been set (i.e. it is zero)
api.llRemoteLoadScriptPin(targetSo.UUID.ToString(), "script", 0, 0, 0);
Assert.IsNull(targetSo.RootPart.Inventory.GetInventoryItem("script"));
// Test that we cannot load a script when the given pin does not match the target
targetSo.RootPart.ScriptAccessPin = 5;
api.llRemoteLoadScriptPin(targetSo.UUID.ToString(), "script", 3, 0, 0);
Assert.IsNull(targetSo.RootPart.Inventory.GetInventoryItem("script"));
// Test that we cannot load into a prim with a different owner
otherOwnedTargetSo.RootPart.ScriptAccessPin = 3;
api.llRemoteLoadScriptPin(otherOwnedTargetSo.UUID.ToString(), "script", 3, 0, 0);
Assert.IsNull(otherOwnedTargetSo.RootPart.Inventory.GetInventoryItem("script"));
// Test that we can load a script when given pin and dest pin match.
targetSo.RootPart.ScriptAccessPin = 3;
api.llRemoteLoadScriptPin(targetSo.UUID.ToString(), "script", 3, 0, 0);
TaskInventoryItem insertedItem = targetSo.RootPart.Inventory.GetInventoryItem("script");
Assert.IsNotNull(insertedItem);
// Test that we can no longer load if access pin is unset
targetSo.RootPart.Inventory.RemoveInventoryItem(insertedItem.ItemID);
Assert.IsNull(targetSo.RootPart.Inventory.GetInventoryItem("script"));
targetSo.RootPart.ScriptAccessPin = 0;
api.llRemoteLoadScriptPin(otherOwnedTargetSo.UUID.ToString(), "script", 3, 0, 0);
Assert.IsNull(otherOwnedTargetSo.RootPart.Inventory.GetInventoryItem("script"));
}
} }
} }

View File

@ -0,0 +1,134 @@
/*
* 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 NUnit.Framework;
using OpenSim.Framework;
using OpenSim.Tests.Common;
using OpenSim.Region.ScriptEngine.Shared;
using OpenSim.Region.Framework.Scenes;
using Nini.Config;
using OpenSim.Region.ScriptEngine.Shared.Api;
using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
using OpenMetaverse;
using OpenSim.Tests.Common.Mock;
using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
namespace OpenSim.Region.ScriptEngine.Shared.Tests
{
[TestFixture]
public class LSL_ApiListTests
{
private LSL_Api m_lslApi;
[SetUp]
public void SetUp()
{
IConfigSource initConfigSource = new IniConfigSource();
IConfig config = initConfigSource.AddConfig("XEngine");
config.Set("Enabled", "true");
Scene scene = new SceneHelpers().SetupScene();
SceneObjectPart part = SceneHelpers.AddSceneObject(scene).RootPart;
XEngine.XEngine engine = new XEngine.XEngine();
engine.Initialise(initConfigSource);
engine.AddRegion(scene);
m_lslApi = new LSL_Api();
m_lslApi.Initialize(engine, part, null);
}
[Test]
public void TestllListFindList()
{
TestHelpers.InMethod();
LSL_List src = new LSL_List(new LSL_Integer(1), new LSL_Integer(2), new LSL_Integer(3));
{
// Test for a single item that should be found
int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4)));
Assert.That(result, Is.EqualTo(-1));
}
{
// Test for a single item that should be found
int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2)));
Assert.That(result, Is.EqualTo(1));
}
{
// Test for a constant that should be found
int result = m_lslApi.llListFindList(src, new LSL_List(ScriptBaseClass.AGENT));
Assert.That(result, Is.EqualTo(0));
}
{
// Test for a list that should be found
int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3)));
Assert.That(result, Is.EqualTo(1));
}
{
// Test for a single item not in the list
int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4)));
Assert.That(result, Is.EqualTo(-1));
}
{
// Test for something that should not be cast
int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_String("4")));
Assert.That(result, Is.EqualTo(-1));
}
{
// Test for a list not in the list
int result
= m_lslApi.llListFindList(
src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3), new LSL_Integer(4)));
Assert.That(result, Is.EqualTo(-1));
}
{
LSL_List srcWithConstants
= new LSL_List(new LSL_Integer(3), ScriptBaseClass.AGENT, ScriptBaseClass.OS_NPC_LAND_AT_TARGET);
// Test for constants that appears in the source list that should be found
int result
= m_lslApi.llListFindList(srcWithConstants, new LSL_List(new LSL_Integer(1), new LSL_Integer(2)));
Assert.That(result, Is.EqualTo(1));
}
}
}
}

View File

@ -589,8 +589,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
if (m_Assemblies.ContainsKey(instance.AssetID)) if (m_Assemblies.ContainsKey(instance.AssetID))
{ {
string assembly = m_Assemblies[instance.AssetID]; string assembly = m_Assemblies[instance.AssetID];
try
{
instance.SaveState(assembly); instance.SaveState(assembly);
} }
catch (Exception e)
{
m_log.Error(
string.Format(
"[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
, e);
}
}
// Clear the event queue and abort the instance thread // Clear the event queue and abort the instance thread
// //
@ -707,8 +719,19 @@ namespace OpenSim.Region.ScriptEngine.XEngine
assembly = m_Assemblies[i.AssetID]; assembly = m_Assemblies[i.AssetID];
} }
try
{
i.SaveState(assembly); i.SaveState(assembly);
} }
catch (Exception e)
{
m_log.Error(
string.Format(
"[XEngine]: Failed to save state of script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
i.PrimName, i.ScriptName, i.ItemID, i.ObjectID, World.Name)
, e);
}
}
instances.Clear(); instances.Clear();
@ -900,6 +923,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
// This delay exists to stop mono problems where script compilation and startup would stop the sim // This delay exists to stop mono problems where script compilation and startup would stop the sim
// working properly for the session. // working properly for the session.
System.Threading.Thread.Sleep(m_StartDelay); System.Threading.Thread.Sleep(m_StartDelay);
m_log.InfoFormat("[XEngine]: Performing initial script startup on {0}", m_Scene.Name);
} }
object[] o; object[] o;
@ -915,13 +940,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
if (m_InitialStartup) if (m_InitialStartup)
if (scriptsStarted % 50 == 0) if (scriptsStarted % 50 == 0)
m_log.InfoFormat( m_log.InfoFormat(
"[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.Name);
} }
} }
if (m_InitialStartup) if (m_InitialStartup)
m_log.InfoFormat( m_log.InfoFormat(
"[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.Name);
// NOTE: Despite having a lockless queue, this lock is required // NOTE: Despite having a lockless queue, this lock is required
// to make sure there is never no compile thread while there // to make sure there is never no compile thread while there
@ -982,10 +1007,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
return false; return false;
} }
UUID assetID = item.AssetID; m_log.DebugFormat(
"[XEngine] Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
//m_log.DebugFormat("[XEngine] Compiling script {0} ({1} on object {2})", UUID assetID = item.AssetID;
// item.Name, itemID.ToString(), part.ParentGroup.RootPart.Name);
ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID); ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID);
@ -1164,10 +1191,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
stateSource, m_MaxScriptQueue); stateSource, m_MaxScriptQueue);
// if (DebugLevel >= 1) // if (DebugLevel >= 1)
m_log.DebugFormat( // m_log.DebugFormat(
"[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", // "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, // part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); // part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
if (presence != null) if (presence != null)
{ {

View File

@ -61,7 +61,7 @@ namespace OpenSim.Region.UserStatistics
/// <summary> /// <summary>
/// User statistics sessions keyed by agent ID /// User statistics sessions keyed by agent ID
/// </summary> /// </summary>
private Dictionary<UUID, UserSessionID> m_sessions = new Dictionary<UUID, UserSessionID>(); private Dictionary<UUID, UserSession> m_sessions = new Dictionary<UUID, UserSession>();
private List<Scene> m_scenes = new List<Scene>(); private List<Scene> m_scenes = new List<Scene>();
private Dictionary<string, IStatsController> reports = new Dictionary<string, IStatsController>(); private Dictionary<string, IStatsController> reports = new Dictionary<string, IStatsController>();
@ -319,14 +319,18 @@ namespace OpenSim.Region.UserStatistics
private void OnMakeRootAgent(ScenePresence agent) private void OnMakeRootAgent(ScenePresence agent)
{ {
// m_log.DebugFormat(
// "[WEB STATS MODULE]: Looking for session {0} for {1} in {2}",
// agent.ControllingClient.SessionId, agent.Name, agent.Scene.Name);
lock (m_sessions) lock (m_sessions)
{ {
UserSessionID uid; UserSession uid;
if (!m_sessions.ContainsKey(agent.UUID)) if (!m_sessions.ContainsKey(agent.UUID))
{ {
UserSessionData usd = UserSessionUtil.newUserSessionData(); UserSessionData usd = UserSessionUtil.newUserSessionData();
uid = new UserSessionID(); uid = new UserSession();
uid.name_f = agent.Firstname; uid.name_f = agent.Firstname;
uid.name_l = agent.Lastname; uid.name_l = agent.Lastname;
uid.session_data = usd; uid.session_data = usd;
@ -411,9 +415,9 @@ namespace OpenSim.Region.UserStatistics
return String.Empty; return String.Empty;
} }
private UserSessionID ParseViewerStats(string request, UUID agentID) private UserSession ParseViewerStats(string request, UUID agentID)
{ {
UserSessionID uid = new UserSessionID(); UserSession uid = new UserSession();
UserSessionData usd; UserSessionData usd;
OSD message = OSDParser.DeserializeLLSDXml(request); OSD message = OSDParser.DeserializeLLSDXml(request);
OSDMap mmap; OSDMap mmap;
@ -425,22 +429,25 @@ namespace OpenSim.Region.UserStatistics
if (!m_sessions.ContainsKey(agentID)) if (!m_sessions.ContainsKey(agentID))
{ {
m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID); m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID);
return new UserSessionID(); return new UserSession();
} }
uid = m_sessions[agentID]; uid = m_sessions[agentID];
// m_log.DebugFormat("[WEB STATS MODULE]: Got session {0} for {1}", uid.session_id, agentID);
} }
else else
{ {
// parse through the beginning to locate the session // parse through the beginning to locate the session
if (message.Type != OSDType.Map) if (message.Type != OSDType.Map)
return new UserSessionID(); return new UserSession();
mmap = (OSDMap)message; mmap = (OSDMap)message;
{ {
UUID sessionID = mmap["session_id"].AsUUID(); UUID sessionID = mmap["session_id"].AsUUID();
if (sessionID == UUID.Zero) if (sessionID == UUID.Zero)
return new UserSessionID(); return new UserSession();
// search through each session looking for the owner // search through each session looking for the owner
@ -459,7 +466,7 @@ namespace OpenSim.Region.UserStatistics
// can't find a session // can't find a session
if (agentID == UUID.Zero) if (agentID == UUID.Zero)
{ {
return new UserSessionID(); return new UserSession();
} }
} }
} }
@ -468,12 +475,12 @@ namespace OpenSim.Region.UserStatistics
usd = uid.session_data; usd = uid.session_data;
if (message.Type != OSDType.Map) if (message.Type != OSDType.Map)
return new UserSessionID(); return new UserSession();
mmap = (OSDMap)message; mmap = (OSDMap)message;
{ {
if (mmap["agent"].Type != OSDType.Map) if (mmap["agent"].Type != OSDType.Map)
return new UserSessionID(); return new UserSession();
OSDMap agent_map = (OSDMap)mmap["agent"]; OSDMap agent_map = (OSDMap)mmap["agent"];
usd.agent_id = agentID; usd.agent_id = agentID;
usd.name_f = uid.name_f; usd.name_f = uid.name_f;
@ -493,17 +500,18 @@ namespace OpenSim.Region.UserStatistics
(float)agent_map["fps"].AsReal()); (float)agent_map["fps"].AsReal());
if (mmap["downloads"].Type != OSDType.Map) if (mmap["downloads"].Type != OSDType.Map)
return new UserSessionID(); return new UserSession();
OSDMap downloads_map = (OSDMap)mmap["downloads"]; OSDMap downloads_map = (OSDMap)mmap["downloads"];
usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal(); usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal();
usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal(); usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal();
usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal(); usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal();
// m_log.DebugFormat("[WEB STATS MODULE]: mmap[\"session_id\"] = [{0}]", mmap["session_id"].AsUUID());
usd.session_id = mmap["session_id"].AsUUID(); usd.session_id = mmap["session_id"].AsUUID();
if (mmap["system"].Type != OSDType.Map) if (mmap["system"].Type != OSDType.Map)
return new UserSessionID(); return new UserSession();
OSDMap system_map = (OSDMap)mmap["system"]; OSDMap system_map = (OSDMap)mmap["system"];
usd.s_cpu = system_map["cpu"].AsString(); usd.s_cpu = system_map["cpu"].AsString();
@ -512,13 +520,13 @@ namespace OpenSim.Region.UserStatistics
usd.s_ram = system_map["ram"].AsInteger(); usd.s_ram = system_map["ram"].AsInteger();
if (mmap["stats"].Type != OSDType.Map) if (mmap["stats"].Type != OSDType.Map)
return new UserSessionID(); return new UserSession();
OSDMap stats_map = (OSDMap)mmap["stats"]; OSDMap stats_map = (OSDMap)mmap["stats"];
{ {
if (stats_map["failures"].Type != OSDType.Map) if (stats_map["failures"].Type != OSDType.Map)
return new UserSessionID(); return new UserSession();
OSDMap stats_failures = (OSDMap)stats_map["failures"]; OSDMap stats_failures = (OSDMap)stats_map["failures"];
usd.f_dropped = stats_failures["dropped"].AsInteger(); usd.f_dropped = stats_failures["dropped"].AsInteger();
usd.f_failed_resends = stats_failures["failed_resends"].AsInteger(); usd.f_failed_resends = stats_failures["failed_resends"].AsInteger();
@ -527,18 +535,18 @@ namespace OpenSim.Region.UserStatistics
usd.f_send_packet = stats_failures["send_packet"].AsInteger(); usd.f_send_packet = stats_failures["send_packet"].AsInteger();
if (stats_map["net"].Type != OSDType.Map) if (stats_map["net"].Type != OSDType.Map)
return new UserSessionID(); return new UserSession();
OSDMap stats_net = (OSDMap)stats_map["net"]; OSDMap stats_net = (OSDMap)stats_map["net"];
{ {
if (stats_net["in"].Type != OSDType.Map) if (stats_net["in"].Type != OSDType.Map)
return new UserSessionID(); return new UserSession();
OSDMap net_in = (OSDMap)stats_net["in"]; OSDMap net_in = (OSDMap)stats_net["in"];
usd.n_in_kb = (float)net_in["kbytes"].AsReal(); usd.n_in_kb = (float)net_in["kbytes"].AsReal();
usd.n_in_pk = net_in["packets"].AsInteger(); usd.n_in_pk = net_in["packets"].AsInteger();
if (stats_net["out"].Type != OSDType.Map) if (stats_net["out"].Type != OSDType.Map)
return new UserSessionID(); return new UserSession();
OSDMap net_out = (OSDMap)stats_net["out"]; OSDMap net_out = (OSDMap)stats_net["out"];
usd.n_out_kb = (float)net_out["kbytes"].AsReal(); usd.n_out_kb = (float)net_out["kbytes"].AsReal();
@ -549,11 +557,18 @@ namespace OpenSim.Region.UserStatistics
uid.session_data = usd; uid.session_data = usd;
m_sessions[agentID] = uid; m_sessions[agentID] = uid;
// m_log.DebugFormat(
// "[WEB STATS MODULE]: Parse data for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id);
return uid; return uid;
} }
private void UpdateUserStats(UserSessionID uid, SqliteConnection db) private void UpdateUserStats(UserSession uid, SqliteConnection db)
{ {
// m_log.DebugFormat(
// "[WEB STATS MODULE]: Updating user stats for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id);
if (uid.session_id == UUID.Zero) if (uid.session_id == UUID.Zero)
return; return;
@ -740,7 +755,6 @@ VALUES
s.min_ping = ArrayMin_f(__ping); s.min_ping = ArrayMin_f(__ping);
s.max_ping = ArrayMax_f(__ping); s.max_ping = ArrayMax_f(__ping);
s.mode_ping = ArrayMode_f(__ping); s.mode_ping = ArrayMode_f(__ping);
} }
#region Statistics #region Statistics
@ -985,7 +999,7 @@ VALUES
} }
#region structs #region structs
public struct UserSessionID public class UserSession
{ {
public UUID session_id; public UUID session_id;
public UUID region_id; public UUID region_id;

View File

@ -84,7 +84,7 @@ namespace OpenSim.Services.AssetService
m_Database = LoadPlugin<IAssetDataPlugin>(dllName); m_Database = LoadPlugin<IAssetDataPlugin>(dllName);
if (m_Database == null) if (m_Database == null)
throw new Exception("Could not find a storage interface in the given module"); throw new Exception(string.Format("Could not find a storage interface in the module {0}", dllName));
m_Database.Initialise(connString); m_Database.Initialise(connString);
@ -96,7 +96,7 @@ namespace OpenSim.Services.AssetService
m_AssetLoader = LoadPlugin<IAssetLoader>(loaderName); m_AssetLoader = LoadPlugin<IAssetLoader>(loaderName);
if (m_AssetLoader == null) if (m_AssetLoader == null)
throw new Exception("Asset loader could not be loaded"); throw new Exception(string.Format("Asset loader could not be loaded from {0}", loaderName));
} }
} }
} }

View File

@ -94,6 +94,7 @@ namespace OpenSim.Services.InventoryService
m_Database = LoadPlugin<IXInventoryData>(dllName, m_Database = LoadPlugin<IXInventoryData>(dllName,
new Object[] {connString, String.Empty}); new Object[] {connString, String.Empty});
if (m_Database == null) if (m_Database == null)
throw new Exception("Could not find a storage interface in the given module"); throw new Exception("Could not find a storage interface in the given module");
} }
@ -230,9 +231,27 @@ namespace OpenSim.Services.InventoryService
{ {
// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID); // m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID);
InventoryFolderBase rootFolder = GetRootFolder(principalID);
if (rootFolder == null)
{
m_log.WarnFormat(
"[XINVENTORY]: Found no root folder for {0} in GetFolderForType() when looking for {1}",
principalID, type);
return null;
}
return GetSystemFolderForType(rootFolder, type);
}
private InventoryFolderBase GetSystemFolderForType(InventoryFolderBase rootFolder, AssetType type)
{
// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID);
XInventoryFolder[] folders = m_Database.GetFolders( XInventoryFolder[] folders = m_Database.GetFolders(
new string[] { "agentID", "type"}, new string[] { "agentID", "parentFolderID", "type"},
new string[] { principalID.ToString(), ((int)type).ToString() }); new string[] { rootFolder.Owner.ToString(), rootFolder.ID.ToString(), ((int)type).ToString() });
if (folders.Length == 0) if (folders.Length == 0)
{ {
@ -308,24 +327,40 @@ namespace OpenSim.Services.InventoryService
if (check != null) if (check != null)
return false; return false;
if (folder.Type == (short)AssetType.Folder if (folder.Type != (short)AssetType.Folder && folder.Type != (short)AssetType.Unknown)
|| folder.Type == (short)AssetType.Unknown
|| folder.Type == (short)AssetType.OutfitFolder
|| GetFolderForType(folder.Owner, (AssetType)(folder.Type)) == null)
{ {
XInventoryFolder xFolder = ConvertFromOpenSim(folder); InventoryFolderBase rootFolder = GetRootFolder(folder.Owner);
return m_Database.StoreFolder(xFolder);
} if (rootFolder == null)
else
{ {
m_log.WarnFormat( m_log.WarnFormat(
"[XINVENTORY]: Folder of type {0} already exists when tried to add {1} to {2} for {3}", "[XINVENTORY]: Found no root folder for {0} in AddFolder() when looking for {1}",
folder.Type, folder.Name, folder.ParentID, folder.Owner); folder.Owner, folder.Type);
}
return false; return false;
} }
// Check we're not trying to add this as a system folder.
if (folder.ParentID == rootFolder.ID)
{
InventoryFolderBase existingSystemFolder
= GetSystemFolderForType(rootFolder, (AssetType)folder.Type);
if (existingSystemFolder != null)
{
m_log.WarnFormat(
"[XINVENTORY]: System folder of type {0} already exists when tried to add {1} to {2} for {3}",
folder.Type, folder.Name, folder.ParentID, folder.Owner);
return false;
}
}
}
XInventoryFolder xFolder = ConvertFromOpenSim(folder);
return m_Database.StoreFolder(xFolder);
}
public virtual bool UpdateFolder(InventoryFolderBase folder) public virtual bool UpdateFolder(InventoryFolderBase folder)
{ {
// m_log.DebugFormat("[XINVENTORY]: Update folder {0} {1} ({2})", folder.Name, folder.Type, folder.ID); // m_log.DebugFormat("[XINVENTORY]: Update folder {0} {1} ({2})", folder.Name, folder.Type, folder.ID);
@ -365,16 +400,7 @@ namespace OpenSim.Services.InventoryService
public virtual bool MoveFolder(InventoryFolderBase folder) public virtual bool MoveFolder(InventoryFolderBase folder)
{ {
XInventoryFolder[] x = m_Database.GetFolders( return m_Database.MoveFolder(folder.ID.ToString(), folder.ParentID.ToString());
new string[] { "folderID" },
new string[] { folder.ID.ToString() });
if (x.Length == 0)
return false;
x[0].parentFolderID = folder.ParentID;
return m_Database.StoreFolder(x[0]);
} }
// We don't check the principal's ID here // We don't check the principal's ID here

View File

@ -245,7 +245,7 @@ namespace OpenSim.Tests.Common
config.AddConfig("Modules"); config.AddConfig("Modules");
config.AddConfig("InventoryService"); config.AddConfig("InventoryService");
config.Configs["Modules"].Set("InventoryServices", "LocalInventoryServicesConnector"); config.Configs["Modules"].Set("InventoryServices", "LocalInventoryServicesConnector");
config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:InventoryService"); config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:XInventoryService");
config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
LocalInventoryServicesConnector inventoryService = new LocalInventoryServicesConnector(); LocalInventoryServicesConnector inventoryService = new LocalInventoryServicesConnector();

View File

@ -199,7 +199,9 @@ namespace OpenSim.Tests.Common
string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None); string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None);
InventoryFolderBase newFolder InventoryFolderBase newFolder
= new InventoryFolderBase(UUID.Random(), components[0], parentFolder.Owner, parentFolder.ID); = new InventoryFolderBase(
UUID.Random(), components[0], parentFolder.Owner, (short)AssetType.Unknown, parentFolder.ID, 0);
inventoryService.AddFolder(newFolder); inventoryService.AddFolder(newFolder);
if (components.Length > 1) if (components.Length > 1)

View File

@ -933,6 +933,11 @@ namespace OpenSim.Tests.Common.Mock
} }
public void Close() public void Close()
{
Close(false);
}
public void Close(bool force)
{ {
// Fire the callback for this connection closing // Fire the callback for this connection closing
// This is necesary to get the presence detector to notice that a client has logged out. // This is necesary to get the presence detector to notice that a client has logged out.

View File

@ -0,0 +1,132 @@
/*
* 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 log4net;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Data;
namespace OpenSim.Tests.Common.Mock
{
public class TestXInventoryDataPlugin : IXInventoryData
{
private Dictionary<UUID, XInventoryFolder> m_allFolders = new Dictionary<UUID, XInventoryFolder>();
private Dictionary<UUID, XInventoryItem> m_allItems = new Dictionary<UUID, XInventoryItem>();
public TestXInventoryDataPlugin(string conn, string realm) {}
public XInventoryItem[] GetItems(string[] fields, string[] vals)
{
List<XInventoryItem> origItems = Get<XInventoryItem>(fields, vals, m_allItems.Values.ToList());
return origItems.Select(i => i.Clone()).ToArray();
}
public XInventoryFolder[] GetFolders(string[] fields, string[] vals)
{
List<XInventoryFolder> origFolders
= Get<XInventoryFolder>(fields, vals, m_allFolders.Values.ToList());
return origFolders.Select(f => f.Clone()).ToArray();
}
private List<T> Get<T>(string[] fields, string[] vals, List<T> inputEntities)
{
List<T> entities = inputEntities;
for (int i = 0; i < fields.Length; i++)
{
entities
= entities.Where(
e =>
{
FieldInfo fi = typeof(T).GetField(fields[i]);
if (fi == null)
throw new NotImplementedException(string.Format("No field {0} for val {1}", fields[i], vals[i]));
return fi.GetValue(e).ToString() == vals[i];
}
).ToList();
}
return entities;
}
public bool StoreFolder(XInventoryFolder folder)
{
m_allFolders[folder.folderID] = folder.Clone();
// Console.WriteLine("Added folder {0} {1}", folder.folderName, folder.folderID);
return true;
}
public bool StoreItem(XInventoryItem item)
{
m_allItems[item.inventoryID] = item.Clone();
// Console.WriteLine("Added item {0} {1}, creator {2}, owner {3}", item.inventoryName, item.inventoryID, item.creatorID, item.avatarID);
return true;
}
public bool DeleteFolders(string field, string val)
{
return DeleteFolders(new string[] { field }, new string[] { val });
}
public bool DeleteFolders(string[] fields, string[] vals)
{
XInventoryFolder[] foldersToDelete = GetFolders(fields, vals);
Array.ForEach(foldersToDelete, f => m_allFolders.Remove(f.folderID));
return true;
}
public bool DeleteItems(string field, string val)
{
return DeleteItems(new string[] { field }, new string[] { val });
}
public bool DeleteItems(string[] fields, string[] vals)
{
XInventoryItem[] itemsToDelete = GetItems(fields, vals);
Array.ForEach(itemsToDelete, i => m_allItems.Remove(i.inventoryID));
return true;
}
public bool MoveItem(string id, string newParent) { throw new NotImplementedException(); }
public bool MoveFolder(string id, string newParent) { throw new NotImplementedException(); }
public XInventoryItem[] GetActiveGestures(UUID principalID) { throw new NotImplementedException(); }
public int GetAssetPermissions(UUID principalID, UUID assetID) { throw new NotImplementedException(); }
}
}

View File

@ -95,6 +95,7 @@ namespace OpenSim.Tests.Common
public static void EnableLogging() public static void EnableLogging()
{ {
log4net.Config.XmlConfigurator.Configure(EnableLoggingConfigStream); log4net.Config.XmlConfigurator.Configure(EnableLoggingConfigStream);
EnableLoggingConfigStream.Position = 0;
} }
/// <summary> /// <summary>

Binary file not shown.

View File

@ -209,49 +209,6 @@ namespace Prebuild.Core.Targets
ss.WriteLine(" <target name=\"{0}\">", "build"); ss.WriteLine(" <target name=\"{0}\">", "build");
ss.WriteLine(" <echo message=\"Build Directory is ${project::get-base-directory()}/${build.dir}\" />"); ss.WriteLine(" <echo message=\"Build Directory is ${project::get-base-directory()}/${build.dir}\" />");
ss.WriteLine(" <mkdir dir=\"${project::get-base-directory()}/${build.dir}\" />"); ss.WriteLine(" <mkdir dir=\"${project::get-base-directory()}/${build.dir}\" />");
ss.WriteLine(" <copy todir=\"${project::get-base-directory()}/${build.dir}\" flatten=\"true\">");
ss.WriteLine(" <fileset basedir=\"${project::get-base-directory()}\">");
foreach (ReferenceNode refr in project.References)
{
if (refr.LocalCopy)
{
ss.WriteLine(" <include name=\"{0}", Helper.NormalizePath(Helper.MakePathRelativeTo(project.FullPath, BuildReference(solution, project, refr)) + "\" />", '/'));
}
}
ss.WriteLine(" </fileset>");
ss.WriteLine(" </copy>");
if (project.ConfigFile != null && project.ConfigFile.Length!=0)
{
ss.Write(" <copy file=\"" + project.ConfigFile + "\" tofile=\"${project::get-base-directory()}/${build.dir}/${project::get-name()}");
if (project.Type == ProjectType.Library)
{
ss.Write(".dll.config\"");
}
else
{
ss.Write(".exe.config\"");
}
ss.WriteLine(" />");
}
// Add the content files to just be copied
ss.WriteLine(" {0}", "<copy todir=\"${project::get-base-directory()}/${build.dir}\">");
ss.WriteLine(" {0}", "<fileset basedir=\".\">");
foreach (string file in project.Files)
{
// Ignore if we aren't content
if (project.Files.GetBuildAction(file) != BuildAction.Content)
continue;
// Create a include tag
ss.WriteLine(" {0}", "<include name=\"" + Helper.NormalizePath(PrependPath(file), '/') + "\" />");
}
ss.WriteLine(" {0}", "</fileset>");
ss.WriteLine(" {0}", "</copy>");
ss.Write(" <csc "); ss.Write(" <csc ");
ss.Write(" target=\"{0}\"", project.Type.ToString().ToLower()); ss.Write(" target=\"{0}\"", project.Type.ToString().ToLower());

View File

@ -87,6 +87,10 @@
;; from the selected region_info_source. ;; from the selected region_info_source.
; allow_regionless = false ; allow_regionless = false
;# {MaxPrimUndos} {} {Maximum number of undos avialable for position, rotation and scale changes of each prim} {} 20
;; Increasing the number of undos available number will increase memory usage.
MaxPrimUndos = 20
;# {NonPhysicalPrimMax} {} {Maximum size of nonphysical prims?} {} 256 ;# {NonPhysicalPrimMax} {} {Maximum size of nonphysical prims?} {} 256
;; Maximum size for non-physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonphysicalPrimMax!). ;; Maximum size for non-physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonphysicalPrimMax!).
; NonphysicalPrimMax = 256 ; NonphysicalPrimMax = 256
@ -675,7 +679,9 @@
;; Maximum number of events to queue for a script (excluding timers) ;; Maximum number of events to queue for a script (excluding timers)
; MaxScriptEventQueue = 300 ; MaxScriptEventQueue = 300
;; Stack size per thread created ;; Stack size per script engine thread in bytes.
;; If you are experiencing StackOverflowExceptions you may want to increase this (e.g. double it).
;; The trade-off may be increased memory usage by the script engine.
; ThreadStackSize = 262144 ; ThreadStackSize = 262144
;# {DeleteScriptsOnStartup} {} {Delete previously compiled script DLLs on startup?} (true false) true ;# {DeleteScriptsOnStartup} {} {Delete previously compiled script DLLs on startup?} (true false) true

View File

@ -85,8 +85,12 @@
;; from the selected region_info_source. ;; from the selected region_info_source.
allow_regionless = false allow_regionless = false
; Maximum size of non physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonphysicalPrimMax!). ; Maximum number of position, rotation and scale changes for each prim that the simulator will store for later undos
NonphysicalPrimMax = 256 ; Increasing this number will increase memory usage.
MaxPrimUndos = 20
; Maximum size of non physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonPhysicalPrimMax!).
NonPhysicalPrimMax = 256
; Maximum size of physical prims. Affects resizing of existing prims. This can be overriden in the region config file. ; Maximum size of physical prims. Affects resizing of existing prims. This can be overriden in the region config file.
PhysicalPrimMax = 10 PhysicalPrimMax = 10
@ -669,8 +673,7 @@
; If true, avatar appearance information is resent to other avatars in the simulator every 60 seconds. ; If true, avatar appearance information is resent to other avatars in the simulator every 60 seconds.
; This may help with some situations where avatars are persistently grey, though it will not help ; This may help with some situations where avatars are persistently grey, though it will not help
; in other situations (e.g. appearance baking failures where the avatar only appears as a cloud to others). ; in other situations (e.g. appearance baking failures where the avatar only appears as a cloud to others).
; This setting is experimental. ResendAppearanceUpdates = true
ResendAppearanceUpdates = false
[Attachments] [Attachments]

Binary file not shown.

View File

@ -54,10 +54,3 @@
; Warning level for cache directory size ; Warning level for cache directory size
;CacheWarnAt = 30000 ;CacheWarnAt = 30000
; Perform a deep scan of all assets within all regions, looking for all assets
; present or referenced. Mark all assets found that are already present in the
; cache, and request all assets that are found that are not already cached (this
; will cause those assets to be cached)
;
DeepScanBeforePurge = true

View File

@ -7,6 +7,16 @@
[AssetService] [AssetService]
ConnectionString = "URI=file:Asset.db,version=3" ConnectionString = "URI=file:Asset.db,version=3"
; The HGAssetService section controls the connection given to the AssetService in a Hypergrid configuration.
; This has to be separate from [AssetService] because the Hypergrid facing connector uses [HGAssetService] for its config data instead.
; However, the internal asset service will still use the [AssetService] section.
; Therefore, you will almost certainly want the ConnectionString in [HGAssetService] to be the same as in [AssetService]
; so that they both access the same database.
; This issue does not apply to normal MySQL/MSSQL configurations, since by default they use the settings in [DatabaseService] and
; do not have separate connection strings for different services.
[HGAssetService]
ConnectionString = "URI=file:Asset.db,version=3"
[InventoryService] [InventoryService]
;ConnectionString = "URI=file:inventory.db,version=3" ;ConnectionString = "URI=file:inventory.db,version=3"
; if you have a legacy inventory store use the connection string below ; if you have a legacy inventory store use the connection string below

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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