From 9ecad5041944ad51a815972ace5366430973503c Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 5 Apr 2010 19:37:02 +0100 Subject: [PATCH 01/35] Partially implement share with group option for object inventory items If serverside permissions are off then this works as expected. Previously, it was impossible for more than one person to edit such items even if permissions were off. If serverside permissions are on then this works as expected if the object was created by an avatar who had the required group active. However, if the group for the object is later set then the contained item is still not editable. This may be linked to a wider bug where the object is still not modifiable by the group anyway --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 15 +++++++++------ .../Region/Framework/Scenes/Scene.Inventory.cs | 1 + .../Scenes/SceneObjectGroup.Inventory.cs | 4 +++- .../Framework/Scenes/SceneObjectPartInventory.cs | 10 +++++++++- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 25f6ef0835..7ccdd58c98 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -669,8 +669,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void ProcessSpecificPacketAsync(object state) { AsyncPacketProcess packetObject = (AsyncPacketProcess)state; - packetObject.result = packetObject.Method(packetObject.ClientView, packetObject.Pack); - + packetObject.result = packetObject.Method(packetObject.ClientView, packetObject.Pack); } #endregion Packet Handling @@ -7683,12 +7682,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP newTaskItem.GroupPermissions = updatetask.InventoryData.GroupMask; newTaskItem.EveryonePermissions = updatetask.InventoryData.EveryoneMask; newTaskItem.NextPermissions = updatetask.InventoryData.NextOwnerMask; + + // Unused? Clicking share with group sets GroupPermissions instead, so perhaps this is something + // different //newTaskItem.GroupOwned=updatetask.InventoryData.GroupOwned; newTaskItem.Type = updatetask.InventoryData.Type; newTaskItem.InvType = updatetask.InventoryData.InvType; newTaskItem.Flags = updatetask.InventoryData.Flags; //newTaskItem.SaleType=updatetask.InventoryData.SaleType; - //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice;; + //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice; newTaskItem.Name = Util.FieldToString(updatetask.InventoryData.Name); newTaskItem.Description = Util.FieldToString(updatetask.InventoryData.Description); newTaskItem.CreationDate = (uint)updatetask.InventoryData.CreationDate; @@ -7696,7 +7698,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP newTaskItem, updatetask.UpdateData.LocalID); } } - } + } return true; } @@ -11088,7 +11090,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (m_debugPacketLevel >= 255) m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack.Type); - + if (!ProcessPacketMethod(Pack)) m_log.Warn("[CLIENT]: unhandled packet " + Pack.Type); @@ -11615,6 +11617,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public PacketMethod method; public bool Async; } + public class AsyncPacketProcess { public bool result = false; @@ -11692,4 +11695,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(dialog, ThrottleOutPacketType.Task); } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 31c0be1aff..3b7f38e575 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1160,6 +1160,7 @@ namespace OpenSim.Region.Framework.Scenes item = LibraryService.LibraryRootFolder.FindItem(itemID); } + // If we've found the item in the user's inventory or in the library if (item != null) { part.ParentGroup.AddInventoryItem(remoteClient, primLocalID, item, copyID); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index 71354b4eac..4034744c58 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -173,7 +173,9 @@ namespace OpenSim.Region.Framework.Scenes item.NextPermissions; taskItem.NextPermissions = item.NextPermissions; taskItem.CurrentPermissions |= 8; - } else { + } + else + { taskItem.BasePermissions = item.BasePermissions; taskItem.CurrentPermissions = item.CurrentPermissions; taskItem.CurrentPermissions |= 8; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 77bf6fe616..2e13f90b66 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -527,6 +527,7 @@ namespace OpenSim.Region.Framework.Scenes item.ParentID = m_part.UUID; item.ParentPartID = m_part.UUID; item.Name = name; + item.GroupID = m_part.GroupID; lock (m_items) { @@ -619,6 +620,12 @@ namespace OpenSim.Region.Framework.Scenes item.ParentID = m_part.UUID; item.ParentPartID = m_part.UUID; item.Flags = m_items[item.ItemID].Flags; + + // If group permissions have been set on, check that the groupID is up to date in case it has + // changed since permissions were last set. + if (item.GroupPermissions != (uint)PermissionMask.None) + item.GroupID = m_part.GroupID; + if (item.AssetID == UUID.Zero) { item.AssetID = m_items[item.ItemID].AssetID; @@ -770,6 +777,7 @@ namespace OpenSim.Region.Framework.Scenes uint everyoneMask = 0; uint baseMask = item.BasePermissions; uint ownerMask = item.CurrentPermissions; + uint groupMask = item.GroupPermissions; invString.AddItemStart(); invString.AddNameValueLine("item_id", item.ItemID.ToString()); @@ -779,7 +787,7 @@ namespace OpenSim.Region.Framework.Scenes invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); - invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0)); + invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); From 1be19c7f42e3f47a89385f8a6fe18b5150e25249 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 5 Apr 2010 19:46:43 +0100 Subject: [PATCH 02/35] log exceptions that end up at the top of a asynchronous viewer packet method call rather than swallowing them --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 7ccdd58c98..516c23b37d 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -641,7 +641,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (pprocessor.Async) { object obj = new AsyncPacketProcess(this, pprocessor.method, packet); - Util.FireAndForget(ProcessSpecificPacketAsync,obj); + Util.FireAndForget(ProcessSpecificPacketAsync, obj); result = true; } else @@ -669,7 +669,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void ProcessSpecificPacketAsync(object state) { AsyncPacketProcess packetObject = (AsyncPacketProcess)state; - packetObject.result = packetObject.Method(packetObject.ClientView, packetObject.Pack); + + try + { + packetObject.result = packetObject.Method(packetObject.ClientView, packetObject.Pack); + } + catch (Exception e) + { + // Make sure that we see any exception caused by the asynchronous operation. + m_log.Error( + string.Format("[LLCLIENTVIEW]: Caught exception while processing {0}", packetObject.Pack), e); + } } #endregion Packet Handling @@ -11695,4 +11705,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(dialog, ThrottleOutPacketType.Task); } } -} \ No newline at end of file +} From 48d2e8309a4b16843687a37b5458d00535e139d8 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 5 Apr 2010 20:42:20 +0100 Subject: [PATCH 03/35] check group membership and powers with the groups module rather than just the client's active group id this resolves the earlier issue where notecards/scripts shared with group could only be edited if the user had that group active --- .../World/Permissions/PermissionsModule.cs | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 0f830e12a1..d9405649b5 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -162,7 +162,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions private Dictionary GrantVB = new Dictionary(); private Dictionary GrantJS = new Dictionary(); private Dictionary GrantYP = new Dictionary(); - private IFriendsModule m_friendsModule = null; + private IFriendsModule m_friendsModule; + private IGroupsModule m_groupsModule; #endregion @@ -386,9 +387,12 @@ namespace OpenSim.Region.CoreModules.World.Permissions m_friendsModule = m_scene.RequestModuleInterface(); if (m_friendsModule == null) - m_log.Error("[PERMISSIONS]: Friends module not found, friend permissions will not work"); - else - m_log.Info("[PERMISSIONS]: Friends module found, friend permissions enabled"); + m_log.Warn("[PERMISSIONS]: Friends module not found, friend permissions will not work"); + + m_groupsModule = m_scene.RequestModuleInterface(); + + if (m_groupsModule == null) + m_log.Warn("[PERMISSIONS]: Groups module not found, group permissions will not work"); } public void Close() @@ -423,14 +427,17 @@ namespace OpenSim.Region.CoreModules.World.Permissions // with the powers requested (powers = 0 for no powers check) protected bool IsGroupMember(UUID groupID, UUID userID, ulong powers) { - ScenePresence sp = m_scene.GetScenePresence(userID); - if (sp != null) - { - IClientAPI client = sp.ControllingClient; + if (null == m_groupsModule) + return false; - return ((groupID == client.ActiveGroupId) && (client.ActiveGroupPowers != 0) && - ((powers == 0) || ((client.ActiveGroupPowers & powers) == powers))); + GroupMembershipData gmd = m_groupsModule.GetMembershipData(groupID, userID); + + if (gmd != null) + { + if (((gmd.GroupPowers != 0) && powers == 0) || (gmd.GroupPowers & powers) == powers) + return true; } + return false; } @@ -721,8 +728,17 @@ namespace OpenSim.Region.CoreModules.World.Permissions permission = false; } +// m_log.DebugFormat( +// "[PERMISSIONS]: group.GroupID = {0}, part.GroupMask = {1}, isGroupMember = {2} for {3}", +// group.GroupID, +// m_scene.GetSceneObjectPart(objId).GroupMask, +// IsGroupMember(group.GroupID, currentUser, 0), +// currentUser); + // Group members should be able to edit group objects - if ((group.GroupID != UUID.Zero) && ((m_scene.GetSceneObjectPart(objId).GroupMask & (uint)PermissionMask.Modify) != 0) && IsGroupMember(group.GroupID, currentUser, 0)) + if ((group.GroupID != UUID.Zero) + && ((m_scene.GetSceneObjectPart(objId).GroupMask & (uint)PermissionMask.Modify) != 0) + && IsGroupMember(group.GroupID, currentUser, 0)) { // Return immediately, so that the administrator can shares group objects return true; @@ -957,7 +973,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericObjectPermission(editorID, objectID, false); } From f302224cafa9ffe8f47cce2274022e1ee2ed37d6 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Mon, 5 Apr 2010 14:52:25 -0700 Subject: [PATCH 04/35] * In the async asset fetch method, cache check before firing any async code. This should alleviate some "thread storm" issues when regions are starting up that hit Mono especially hard --- .../SimianGrid/SimianAssetServiceConnector.cs | 109 ++++++++++-------- 1 file changed, 62 insertions(+), 47 deletions(-) diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs index 27434ad0de..4a7522fcfb 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs @@ -112,59 +112,15 @@ namespace OpenSim.Services.Connectors.SimianGrid public AssetBase Get(string id) { - AssetBase asset = null; - // Cache fetch if (m_cache != null) { - asset = m_cache.Get(id); + AssetBase asset = m_cache.Get(id); if (asset != null) return asset; } - Uri url; - - // Determine if id is an absolute URL or a grid-relative UUID - if (!Uri.TryCreate(id, UriKind.Absolute, out url)) - url = new Uri(m_serverUrl + id); - - try - { - HttpWebRequest request = UntrustedHttpWebRequest.Create(url); - - using (WebResponse response = request.GetResponse()) - { - using (Stream responseStream = response.GetResponseStream()) - { - string creatorID = response.Headers.GetOne("X-Asset-Creator-Id") ?? String.Empty; - - // Create the asset object - asset = new AssetBase(id, String.Empty, SLUtil.ContentTypeToSLAssetType(response.ContentType), creatorID); - - UUID assetID; - if (UUID.TryParse(id, out assetID)) - asset.FullID = assetID; - - // Grab the asset data from the response stream - using (MemoryStream stream = new MemoryStream()) - { - responseStream.CopyTo(stream, Int32.MaxValue); - asset.Data = stream.ToArray(); - } - } - } - - // Cache store - if (m_cache != null && asset != null) - m_cache.Cache(asset); - - return asset; - } - catch (Exception ex) - { - m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset GET from " + url + " failed: " + ex.Message); - return null; - } + return GetRemote(id); } /// @@ -245,10 +201,21 @@ namespace OpenSim.Services.Connectors.SimianGrid /// True if the id was parseable, false otherwise public bool Get(string id, Object sender, AssetRetrieved handler) { + // Cache fetch + if (m_cache != null) + { + AssetBase asset = m_cache.Get(id); + if (asset != null) + { + Util.FireAndForget(delegate(object o) { handler(id, sender, asset); }); + return true; + } + } + Util.FireAndForget( delegate(object o) { - AssetBase asset = Get(id); + AssetBase asset = GetRemote(id); handler(id, sender, asset); } ); @@ -406,5 +373,53 @@ namespace OpenSim.Services.Connectors.SimianGrid } #endregion IAssetService + + private AssetBase GetRemote(string id) + { + AssetBase asset = null; + Uri url; + + // Determine if id is an absolute URL or a grid-relative UUID + if (!Uri.TryCreate(id, UriKind.Absolute, out url)) + url = new Uri(m_serverUrl + id); + + try + { + HttpWebRequest request = UntrustedHttpWebRequest.Create(url); + + using (WebResponse response = request.GetResponse()) + { + using (Stream responseStream = response.GetResponseStream()) + { + string creatorID = response.Headers.GetOne("X-Asset-Creator-Id") ?? String.Empty; + + // Create the asset object + asset = new AssetBase(id, String.Empty, SLUtil.ContentTypeToSLAssetType(response.ContentType), creatorID); + + UUID assetID; + if (UUID.TryParse(id, out assetID)) + asset.FullID = assetID; + + // Grab the asset data from the response stream + using (MemoryStream stream = new MemoryStream()) + { + responseStream.CopyTo(stream, Int32.MaxValue); + asset.Data = stream.ToArray(); + } + } + } + + // Cache store + if (m_cache != null && asset != null) + m_cache.Cache(asset); + + return asset; + } + catch (Exception ex) + { + m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset GET from " + url + " failed: " + ex.Message); + return null; + } + } } } From 80346ad2e246a363dcf4c9a2819b52b1d7a0739c Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 5 Apr 2010 19:56:03 -0700 Subject: [PATCH 05/35] * May fix mantis #4603. * My local git wants to commit the groups files for line endings, I'm gonna let it do it. --- .../RemoteController/RemoteAdminPlugin.cs | 4 +- .../XmlRpcGroups/GroupsMessagingModule.cs | 128 ++++++++-------- .../Avatar/XmlRpcGroups/GroupsModule.cs | 6 +- .../XmlRpcGroups/IGroupsServicesConnector.cs | 12 +- .../SimianGroupsServicesConnectorModule.cs | 104 ++++++------- .../XmlRpcGroupsServicesConnectorModule.cs | 144 +++++++++--------- 6 files changed, 200 insertions(+), 198 deletions(-) diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index c59ea28132..5a23c90185 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -1012,7 +1012,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController throw new Exception(String.Format("Account {0} {1} already exists", firstname, lastname)); account = new UserAccount(scopeID, firstname, lastname, email); - // REFACTORING PROBLEM: no method to set the password! bool success = m_app.SceneManager.CurrentOrFirstScene.UserAccountService.StoreUserAccount(account); @@ -1020,6 +1019,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController throw new Exception(String.Format("failed to create new user {0} {1}", firstname, lastname)); + // Store the password + m_app.SceneManager.CurrentOrFirstScene.AuthenticationService.SetPassword(account.PrincipalID, passwd); + GridRegion home = m_app.SceneManager.CurrentOrFirstScene.GridService.GetRegionByPosition(scopeID, (int)(regX * Constants.RegionSize), (int)(regY * Constants.RegionSize)); if (home == null) diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs index 17a53493fb..185d44de80 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs @@ -49,9 +49,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private List m_sceneList = new List(); - private IMessageTransferModule m_msgTransferModule = null; - - private IGroupsServicesConnector m_groupData = null; + private IMessageTransferModule m_msgTransferModule = null; + + private IGroupsServicesConnector m_groupData = null; // Config Options private bool m_groupMessagingEnabled = false; @@ -108,13 +108,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (!m_groupMessagingEnabled) return; - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + m_groupData = scene.RequestModuleInterface(); - // No groups module, no groups messaging + // No groups module, no groups messaging if (m_groupData == null) - { + { m_log.Error("[GROUPS-MESSAGING]: Could not get IGroupsServicesConnector, GroupsMessagingModule is now disabled."); Close(); m_groupMessagingEnabled = false; @@ -190,9 +190,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups #endregion - /// - /// Not really needed, but does confirm that the group exists. - /// + /// + /// Not really needed, but does confirm that the group exists. + /// public bool StartGroupChatSession(UUID agentID, UUID groupID) { if (m_debugEnabled) @@ -201,7 +201,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups GroupRecord groupInfo = m_groupData.GetGroupRecord(agentID, groupID, null); if (groupInfo != null) - { + { return true; } else @@ -213,11 +213,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void SendMessageToGroup(GridInstantMessage im, UUID groupID) { if (m_debugEnabled) - m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - + m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + foreach (GroupMembersData member in m_groupData.GetGroupMembers(UUID.Zero, groupID)) - { + { if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) { // Don't deliver messages to people who have dropped this session @@ -226,7 +226,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } // Copy Message - GridInstantMessage msg = new GridInstantMessage(); + GridInstantMessage msg = new GridInstantMessage(); msg.imSessionID = groupID.Guid; msg.fromAgentName = im.fromAgentName; msg.message = im.message; @@ -259,13 +259,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } } - #region SimGridEventHandlers - - void OnClientLogin(IClientAPI client) - { + #region SimGridEventHandlers + + void OnClientLogin(IClientAPI client) + { if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: OnInstantMessage registered for {0}", client.Name); - - + + } private void OnNewClient(IClientAPI client) @@ -303,28 +303,28 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private void ProcessMessageFromGroupSession(GridInstantMessage msg) { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Session message from {0} going to agent {1}", msg.fromAgentName, msg.toAgentID); - - UUID AgentID = new UUID(msg.fromAgentID); + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Session message from {0} going to agent {1}", msg.fromAgentName, msg.toAgentID); + + UUID AgentID = new UUID(msg.fromAgentID); UUID GroupID = new UUID(msg.imSessionID); switch (msg.dialog) { - case (byte)InstantMessageDialog.SessionAdd: + case (byte)InstantMessageDialog.SessionAdd: m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); break; - case (byte)InstantMessageDialog.SessionDrop: + case (byte)InstantMessageDialog.SessionDrop: m_groupData.AgentDroppedFromGroupChatSession(AgentID, GroupID); break; - case (byte)InstantMessageDialog.SessionSend: - if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID) + case (byte)InstantMessageDialog.SessionSend: + if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID) && !m_groupData.hasAgentBeenInvitedToGroupChatSession(AgentID, GroupID) ) { // Agent not in session and hasn't dropped from session - // Add them to the session for now, and Invite them + // Add them to the session for now, and Invite them m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); UUID toAgentID = new UUID(msg.toAgentID); @@ -336,10 +336,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Sending chatterbox invite instant message"); - // Force? open the group session dialog??? + // Force? open the group session dialog??? // and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg); IEventQueue eq = activeClient.Scene.RequestModuleInterface(); - eq.ChatterboxInvitation( + eq.ChatterboxInvitation( GroupID , groupInfo.GroupName , new UUID(msg.fromAgentID) @@ -357,7 +357,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups , Utils.StringToBytes(groupInfo.GroupName) ); - eq.ChatterBoxSessionAgentListUpdates( + eq.ChatterBoxSessionAgentListUpdates( new UUID(GroupID) , new UUID(msg.fromAgentID) , new UUID(msg.toAgentID) @@ -367,7 +367,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups ); } } - } + } else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID)) { // User hasn't dropped, so they're in the session, @@ -394,8 +394,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups #endregion - - #region ClientEvents + + #region ClientEvents private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) { if (m_debugEnabled) @@ -407,23 +407,23 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Start group IM session if ((im.dialog == (byte)InstantMessageDialog.SessionGroupStart)) - { - if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING]: imSessionID({0}) toAgentID({1})", im.imSessionID, im.toAgentID); - - UUID GroupID = new UUID(im.imSessionID); - UUID AgentID = new UUID(im.fromAgentID); - + { + if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING]: imSessionID({0}) toAgentID({1})", im.imSessionID, im.toAgentID); + + UUID GroupID = new UUID(im.imSessionID); + UUID AgentID = new UUID(im.fromAgentID); + GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); if (groupInfo != null) - { + { m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, GroupID); IEventQueue queue = remoteClient.Scene.RequestModuleInterface(); - queue.ChatterBoxSessionAgentListUpdates( - GroupID + queue.ChatterBoxSessionAgentListUpdates( + GroupID , AgentID , new UUID(im.toAgentID) , false //canVoiceChat @@ -435,16 +435,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Send a message from locally connected client to a group if ((im.dialog == (byte)InstantMessageDialog.SessionSend)) - { - UUID GroupID = new UUID(im.imSessionID); - UUID AgentID = new UUID(im.fromAgentID); + { + UUID GroupID = new UUID(im.imSessionID); + UUID AgentID = new UUID(im.fromAgentID); if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Send message to session for group {0} with session ID {1}", GroupID, im.imSessionID.ToString()); - //If this agent is sending a message, then they want to be in the session - m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); - + //If this agent is sending a message, then they want to be in the session + m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); + SendMessageToGroup(im, GroupID); } } @@ -501,7 +501,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// Try to find an active IClientAPI reference for agentID giving preference to root connections /// private IClientAPI GetActiveClient(UUID agentID) - { + { if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Looking for local client {0}", agentID); IClientAPI child = null; @@ -514,26 +514,26 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { ScenePresence user = (ScenePresence)scene.Entities[agentID]; if (!user.IsChildAgent) - { - if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Found root agent for client : {0}", user.ControllingClient.Name); + { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Found root agent for client : {0}", user.ControllingClient.Name); return user.ControllingClient; } else - { - if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Found child agent for client : {0}", user.ControllingClient.Name); + { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Found child agent for client : {0}", user.ControllingClient.Name); child = user.ControllingClient; } } } - // If we didn't find a root, then just return whichever child we found, or null if none - if (child == null) - { - if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Could not find local client for agent : {0}", agentID); - } - else - { - if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Returning child agent for client : {0}", child.Name); + // If we didn't find a root, then just return whichever child we found, or null if none + if (child == null) + { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Could not find local client for agent : {0}", agentID); + } + else + { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Returning child agent for client : {0}", child.Name); } return child; } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index e5dab9396b..56c0d985f1 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -175,13 +175,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; + scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; // The InstantMessageModule itself doesn't do this, // so lets see if things explode if we don't do it // scene.EventManager.OnClientClosed += OnClientClosed; - } - + } + public void RemoveRegion(Scene scene) { if (!m_groupsEnabled) diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs index 54ffc81002..a046e094cd 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs @@ -70,12 +70,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups void AddGroupNotice(UUID RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket); GroupNoticeInfo GetGroupNotice(UUID RequestingAgentID, UUID noticeID); - List GetGroupNotices(UUID RequestingAgentID, UUID GroupID); - - void ResetAgentGroupChatSessions(UUID agentID); - bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID); - bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID); - void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID); + List GetGroupNotices(UUID RequestingAgentID, UUID GroupID); + + void ResetAgentGroupChatSessions(UUID agentID); + bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID); + bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID); + void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID); void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID); } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs index 4867c01192..669373f125 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs @@ -203,12 +203,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; } - m_log.InfoFormat("[GROUPS-CONNECTOR]: Initializing {0}", this.Name); - + m_log.InfoFormat("[GROUPS-CONNECTOR]: Initializing {0}", this.Name); + m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); if ((m_groupsServerURI == null) || (m_groupsServerURI == string.Empty)) - { + { m_log.ErrorFormat("Please specify a valid Simian Server for GroupsServerURI in OpenSim.ini, [Groups]"); m_connectorEnabled = false; return; @@ -1000,53 +1000,53 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups SimianAddGeneric(groupID, "GroupNotice", noticeID.ToString(), Notice); } - #endregion - - #region GroupSessionTracking - - public void ResetAgentGroupChatSessions(UUID agentID) - { - Dictionary agentSessions; - - if (SimianGetGenericEntries(agentID, "GroupSessionDropped", out agentSessions)) - { - foreach (string GroupID in agentSessions.Keys) - { - SimianRemoveGenericEntry(agentID, "GroupSessionDropped", GroupID); - } - } - - if (SimianGetGenericEntries(agentID, "GroupSessionInvited", out agentSessions)) - { - foreach (string GroupID in agentSessions.Keys) - { - SimianRemoveGenericEntry(agentID, "GroupSessionInvited", GroupID); - } - } - } - - public bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID) - { - OSDMap session; - return SimianGetGenericEntry(agentID, "GroupSessionDropped", groupID.ToString(), out session); - } - - public void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID) - { - SimianAddGeneric(agentID, "GroupSessionDropped", groupID.ToString(), new OSDMap()); - } - - public void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID) - { - SimianAddGeneric(agentID, "GroupSessionInvited", groupID.ToString(), new OSDMap()); - } - - public bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID) - { - OSDMap session; - return SimianGetGenericEntry(agentID, "GroupSessionDropped", groupID.ToString(), out session); - } - + #endregion + + #region GroupSessionTracking + + public void ResetAgentGroupChatSessions(UUID agentID) + { + Dictionary agentSessions; + + if (SimianGetGenericEntries(agentID, "GroupSessionDropped", out agentSessions)) + { + foreach (string GroupID in agentSessions.Keys) + { + SimianRemoveGenericEntry(agentID, "GroupSessionDropped", GroupID); + } + } + + if (SimianGetGenericEntries(agentID, "GroupSessionInvited", out agentSessions)) + { + foreach (string GroupID in agentSessions.Keys) + { + SimianRemoveGenericEntry(agentID, "GroupSessionInvited", GroupID); + } + } + } + + public bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID) + { + OSDMap session; + return SimianGetGenericEntry(agentID, "GroupSessionDropped", groupID.ToString(), out session); + } + + public void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID) + { + SimianAddGeneric(agentID, "GroupSessionDropped", groupID.ToString(), new OSDMap()); + } + + public void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID) + { + SimianAddGeneric(agentID, "GroupSessionInvited", groupID.ToString(), new OSDMap()); + } + + public bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID) + { + OSDMap session; + return SimianGetGenericEntry(agentID, "GroupSessionDropped", groupID.ToString(), out session); + } + #endregion private void EnsureRoleNotSelectedByMember(UUID groupID, UUID roleID, UUID userID) @@ -1321,8 +1321,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return false; } } - #endregion - + #endregion + } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index 8e7aa687e2..523dfbe356 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -68,14 +68,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private string m_groupReadKey = string.Empty; private string m_groupWriteKey = string.Empty; - private IUserAccountService m_accountService = null; - - // Used to track which agents are have dropped from a group chat session - // Should be reset per agent, on logon - // TODO: move this to Flotsam XmlRpc Service - // SessionID, List - private Dictionary> m_groupsAgentsDroppedFromChatSession = new Dictionary>(); - private Dictionary> m_groupsAgentsInvitedToChatSession = new Dictionary>(); + private IUserAccountService m_accountService = null; + + // Used to track which agents are have dropped from a group chat session + // Should be reset per agent, on logon + // TODO: move this to Flotsam XmlRpc Service + // SessionID, List + private Dictionary> m_groupsAgentsDroppedFromChatSession = new Dictionary>(); + private Dictionary> m_groupsAgentsInvitedToChatSession = new Dictionary>(); #region IRegionModuleBase Members @@ -111,12 +111,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; } - m_log.InfoFormat("[GROUPS-CONNECTOR]: Initializing {0}", this.Name); - + m_log.InfoFormat("[GROUPS-CONNECTOR]: Initializing {0}", this.Name); + m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); if ((m_groupsServerURI == null) || (m_groupsServerURI == string.Empty)) - { + { m_log.ErrorFormat("Please specify a valid URL for GroupsServerURI in OpenSim.ini, [Groups]"); m_connectorEnabled = false; return; @@ -766,67 +766,67 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups - #endregion - - #region GroupSessionTracking - - public void ResetAgentGroupChatSessions(UUID agentID) - { - foreach (List agentList in m_groupsAgentsDroppedFromChatSession.Values) - { - agentList.Remove(agentID); - } - } - - public bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID) - { - // If we're tracking this group, and we can find them in the tracking, then they've been invited - return m_groupsAgentsInvitedToChatSession.ContainsKey(groupID) - && m_groupsAgentsInvitedToChatSession[groupID].Contains(agentID); - } - - public bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID) - { - // If we're tracking drops for this group, - // and we find them, well... then they've dropped - return m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID) - && m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID); - } - - public void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID) - { - if (m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID)) - { - // If not in dropped list, add - if (!m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID)) - { - m_groupsAgentsDroppedFromChatSession[groupID].Add(agentID); - } - } - } - - public void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID) - { - // Add Session Status if it doesn't exist for this session - CreateGroupChatSessionTracking(groupID); - - // If nessesary, remove from dropped list - if (m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID)) - { - m_groupsAgentsDroppedFromChatSession[groupID].Remove(agentID); - } - } - - private void CreateGroupChatSessionTracking(UUID groupID) - { - if (!m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID)) - { - m_groupsAgentsDroppedFromChatSession.Add(groupID, new List()); - m_groupsAgentsInvitedToChatSession.Add(groupID, new List()); - } - - } - #endregion + #endregion + + #region GroupSessionTracking + + public void ResetAgentGroupChatSessions(UUID agentID) + { + foreach (List agentList in m_groupsAgentsDroppedFromChatSession.Values) + { + agentList.Remove(agentID); + } + } + + public bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID) + { + // If we're tracking this group, and we can find them in the tracking, then they've been invited + return m_groupsAgentsInvitedToChatSession.ContainsKey(groupID) + && m_groupsAgentsInvitedToChatSession[groupID].Contains(agentID); + } + + public bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID) + { + // If we're tracking drops for this group, + // and we find them, well... then they've dropped + return m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID) + && m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID); + } + + public void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID) + { + if (m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID)) + { + // If not in dropped list, add + if (!m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID)) + { + m_groupsAgentsDroppedFromChatSession[groupID].Add(agentID); + } + } + } + + public void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID) + { + // Add Session Status if it doesn't exist for this session + CreateGroupChatSessionTracking(groupID); + + // If nessesary, remove from dropped list + if (m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID)) + { + m_groupsAgentsDroppedFromChatSession[groupID].Remove(agentID); + } + } + + private void CreateGroupChatSessionTracking(UUID groupID) + { + if (!m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID)) + { + m_groupsAgentsDroppedFromChatSession.Add(groupID, new List()); + m_groupsAgentsInvitedToChatSession.Add(groupID, new List()); + } + + } + #endregion #region XmlRpcHashtableMarshalling private GroupProfileData GroupProfileHashtableToGroupProfileData(Hashtable groupProfile) From 5fc9fe70af3c076492a537c8456a14b9f8cfa485 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 6 Apr 2010 19:38:01 -0700 Subject: [PATCH 06/35] Added NullInventoryData for unit tests and quick try-outs of the services in 64-bit machines (no SQLite). --- OpenSim/Data/Null/NullInventoryData.cs | 193 +++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 OpenSim/Data/Null/NullInventoryData.cs diff --git a/OpenSim/Data/Null/NullInventoryData.cs b/OpenSim/Data/Null/NullInventoryData.cs new file mode 100644 index 0000000000..8f196e2018 --- /dev/null +++ b/OpenSim/Data/Null/NullInventoryData.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; + +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data.Null +{ + /// + /// This class is completely null. + /// + public class NullInventoryData : IInventoryDataPlugin + { + public string Version { get { return "1.0.0.0"; } } + + public void Initialise() + { + } + + public void Dispose() + { + // Do nothing. + } + + public string Name + { + get { return "Null Inventory Data Interface"; } + } + + public void Initialise(string connect) + { + } + + + /// + /// Returns all descendent folders of this folder. Does not return the parent folder itself. + /// + /// The folder to get subfolders for + /// A list of inventory folders + public List getFolderHierarchy(UUID parentID) + { + return new List(); + } + + /// + /// Returns a list of inventory items contained within the specified folder + /// + /// The UUID of the target folder + /// A List of InventoryItemBase items + public List getInventoryInFolder(UUID folderID) + { + return new List(); + } + + /// + /// Returns a list of the root folders within a users inventory + /// + /// The user whos inventory is to be searched + /// A list of folder objects + public List getUserRootFolders(UUID user) + { + return new List(); + } + + /// + /// Returns the users inventory root folder. + /// + /// The UUID of the user who is having inventory being returned + /// Root inventory folder, null if no root inventory folder was found + public InventoryFolderBase getUserRootFolder(UUID user) + { + return null; + } + + /// + /// Returns a list of inventory folders contained in the folder 'parentID' + /// + /// The folder to get subfolders for + /// A list of inventory folders + public List getInventoryFolders(UUID parentID) + { + return new List(); + } + + /// + /// Returns an inventory item by its UUID + /// + /// The UUID of the item to be returned + /// A class containing item information + public InventoryItemBase getInventoryItem(UUID item) + { + return null; + } + + /// + /// Returns a specified inventory folder by its UUID + /// + /// The UUID of the folder to be returned + /// A class containing folder information + public InventoryFolderBase getInventoryFolder(UUID folder) + { + return null; + } + + /// + /// Creates a new inventory item based on item + /// + /// The item to be created + public void addInventoryItem(InventoryItemBase item) + { + } + + /// + /// Updates an inventory item with item (updates based on ID) + /// + /// The updated item + public void updateInventoryItem(InventoryItemBase item) + { + } + + /// + /// + /// + /// + public void deleteInventoryItem(UUID item) + { + } + + /// + /// + /// + /// + public InventoryItemBase queryInventoryItem(UUID item) + { + return null; + } + + /// + /// + /// + /// + public InventoryFolderBase queryInventoryFolder(UUID folder) + { + return null; + } + + /// + /// Adds a new folder specified by folder + /// + /// The inventory folder + public void addInventoryFolder(InventoryFolderBase folder) + { + } + + /// + /// Updates a folder based on its ID with folder + /// + /// The inventory folder + public void updateInventoryFolder(InventoryFolderBase folder) + { + } + + /// + /// Updates a folder based on its ID with folder + /// + /// The inventory folder + public void moveInventoryFolder(InventoryFolderBase folder) + { + } + + /// + /// Deletes a folder. Thie will delete both the folder itself and its contents (items and descendent folders) + /// + /// The id of the folder + public void deleteInventoryFolder(UUID folder) + { + } + + /// + /// Returns all activated gesture-items in the inventory of the specified avatar. + /// + /// + /// The of the avatar + /// + /// + /// The list of gestures (s) + /// + public List fetchActiveGestures(UUID avatarID) + { + return new List(); + } + } +} From 542abb9c43da40779eca2e09cec92e6fece159fd Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Wed, 7 Apr 2010 09:58:16 -0700 Subject: [PATCH 07/35] * Fixing incorrect documentation for the continuation passing style IAssetService.Get() method * Changing the SimianGrid asset service connector to match the corrected documentation --- .../Connectors/SimianGrid/SimianAssetServiceConnector.cs | 2 +- OpenSim/Services/Interfaces/IAssetService.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs index 4a7522fcfb..36c51c3075 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs @@ -207,7 +207,7 @@ namespace OpenSim.Services.Connectors.SimianGrid AssetBase asset = m_cache.Get(id); if (asset != null) { - Util.FireAndForget(delegate(object o) { handler(id, sender, asset); }); + handler(id, sender, asset); return true; } } diff --git a/OpenSim/Services/Interfaces/IAssetService.cs b/OpenSim/Services/Interfaces/IAssetService.cs index 6dfe78d724..f8bedfe1a3 100644 --- a/OpenSim/Services/Interfaces/IAssetService.cs +++ b/OpenSim/Services/Interfaces/IAssetService.cs @@ -51,7 +51,8 @@ namespace OpenSim.Services.Interfaces byte[] GetData(string id); /// - /// Get an asset asynchronously + /// Get an asset synchronously or asynchronously (depending on whether + /// it is locally cached) and fire a callback with the fetched asset /// /// The asset id /// Represents the requester. Passed back via the handler From 3f6c4c150e3910e79ee3dc94f9304c16265512c0 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Thu, 8 Apr 2010 12:31:44 -0700 Subject: [PATCH 08/35] * Adds IAssetService.GetCached() to allow asset fetching from the local cache only * Adds GetTextureModule that implements the "GetTexture" capability, aka HTTP texture fetching. This is a significantly optimized path that does not require any server-side JPEG2000 decoding, texture priority queue, or UDP file transfer * Sanity check for null reference in LLClientView.RefreshGroupMembership() --- .../ClientStack/LindenUDP/LLClientView.cs | 7 +- .../CoreModules/Asset/FlotsamAssetCache.cs | 5 + .../Avatar/Assets/GetTextureModule.cs | 220 ++++++++++++++++++ .../Asset/HGAssetBroker.cs | 8 + .../Asset/LocalAssetServiceConnector.cs | 8 + OpenSim/Services/AssetService/AssetService.cs | 5 + .../Connectors/Asset/AssetServiceConnector.cs | 8 + .../Asset/HGAssetServiceConnector.cs | 14 ++ .../SimianGrid/SimianAssetServiceConnector.cs | 8 + OpenSim/Services/Interfaces/IAssetService.cs | 7 + OpenSim/Tests/Common/Mock/MockAssetService.cs | 5 + 11 files changed, 293 insertions(+), 2 deletions(-) create mode 100644 OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 516c23b37d..51ab281cad 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -11302,9 +11302,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_groupPowers.Clear(); - for (int i = 0; i < GroupMembership.Length; i++) + if (GroupMembership != null) { - m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers; + for (int i = 0; i < GroupMembership.Length; i++) + { + m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers; + } } } } diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 37cdaae2bd..9eaa758bd5 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -406,6 +406,11 @@ namespace Flotsam.RegionModules.AssetCache return asset; } + public AssetBase GetCached(string id) + { + return Get(id); + } + public void Expire(string id) { if (m_LogLevel >= 2) diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs new file mode 100644 index 0000000000..53d2cefeac --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs @@ -0,0 +1,220 @@ +/* + * 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; +using System.Collections.Specialized; +using System.Reflection; +using System.IO; +using System.Web; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; + +namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps +{ + #region Stream Handler + + public delegate byte[] StreamHandlerCallback(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse); + + public class StreamHandler : BaseStreamHandler + { + StreamHandlerCallback m_callback; + + public StreamHandler(string httpMethod, string path, StreamHandlerCallback callback) + : base(httpMethod, path) + { + m_callback = callback; + } + + public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + return m_callback(path, request, httpRequest, httpResponse); + } + } + + #endregion Stream Handler + + public class GetTextureModule : IRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Scene m_scene; + private IAssetService m_assetService; + + #region IRegionModule Members + + public void Initialise(Scene pScene, IConfigSource pSource) + { + m_scene = pScene; + } + + public void PostInitialise() + { + m_assetService = m_scene.RequestModuleInterface(); + m_scene.EventManager.OnRegisterCaps += RegisterCaps; + } + + public void Close() { } + + public string Name { get { return "GetTextureModule"; } } + public bool IsSharedModule { get { return false; } } + + public void RegisterCaps(UUID agentID, Caps caps) + { + UUID capID = UUID.Random(); + + m_log.Info("[GETTEXTURE]: /CAPS/" + capID); + caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture)); + } + + #endregion + + private byte[] ProcessGetTexture(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + // TODO: Change this to a config option + const string REDIRECT_URL = null; + + // Try to parse the texture ID from the request URL + NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); + string textureStr = query.GetOne("texture_id"); + + if (m_assetService == null) + { + m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service"); + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + return null; + } + + UUID textureID; + if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID)) + { + AssetBase texture; + + if (!String.IsNullOrEmpty(REDIRECT_URL)) + { + // Only try to fetch locally cached textures. Misses are redirected + texture = m_assetService.GetCached(textureID.ToString()); + + if (texture != null) + { + SendTexture(httpRequest, httpResponse, texture); + } + else + { + string textureUrl = REDIRECT_URL + textureID.ToString(); + m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl); + httpResponse.RedirectLocation = textureUrl; + } + } + else + { + // Fetch locally or remotely. Misses return a 404 + texture = m_assetService.Get(textureID.ToString()); + + if (texture != null) + { + SendTexture(httpRequest, httpResponse, texture); + } + else + { + m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found"); + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + } + } + } + else + { + m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url); + } + + httpResponse.Send(); + return null; + } + + private void SendTexture(OSHttpRequest request, OSHttpResponse response, AssetBase texture) + { + string range = request.Headers.GetOne("Range"); + if (!String.IsNullOrEmpty(range)) + { + // Range request + int start, end; + if (TryParseRange(range, out start, out end)) + { + end = Utils.Clamp(end, 1, texture.Data.Length); + start = Utils.Clamp(start, 0, end - 1); + + m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); + + if (end - start < texture.Data.Length) + response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; + + response.ContentLength = end - start; + response.ContentType = texture.Metadata.ContentType; + + response.Body.Write(texture.Data, start, end - start); + } + else + { + m_log.Warn("Malformed Range header: " + range); + response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest; + } + } + else + { + // Full content request + response.ContentLength = texture.Data.Length; + response.ContentType = texture.Metadata.ContentType; + response.Body.Write(texture.Data, 0, texture.Data.Length); + } + } + + private bool TryParseRange(string header, out int start, out int end) + { + if (header.StartsWith("bytes=")) + { + string[] rangeValues = header.Substring(6).Split('-'); + if (rangeValues.Length == 2) + { + if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end)) + return true; + } + } + + start = end = 0; + return false; + } + } +} diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs index af2f3d6558..ebd6bbdcfa 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs @@ -229,6 +229,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset return asset; } + public AssetBase GetCached(string id) + { + if (m_Cache != null) + return m_Cache.Get(id); + + return null; + } + public AssetMetadata GetMetadata(string id) { AssetBase asset = null; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs index 50348da728..1b3419d12f 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs @@ -165,6 +165,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset return asset; } + public AssetBase GetCached(string id) + { + if (m_Cache != null) + return m_Cache.Get(id); + + return null; + } + public AssetMetadata GetMetadata(string id) { AssetBase asset = null; diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs index b9723a84b3..ed87f3f6fc 100644 --- a/OpenSim/Services/AssetService/AssetService.cs +++ b/OpenSim/Services/AssetService/AssetService.cs @@ -93,6 +93,11 @@ namespace OpenSim.Services.AssetService return m_Database.GetAsset(assetID); } + public AssetBase GetCached(string id) + { + return Get(id); + } + public AssetMetadata GetMetadata(string id) { UUID assetID; diff --git a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs index a5c157d7f2..65b3537041 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs @@ -111,6 +111,14 @@ namespace OpenSim.Services.Connectors return asset; } + public AssetBase GetCached(string id) + { + if (m_Cache != null) + return m_Cache.Get(id); + + return null; + } + public AssetMetadata GetMetadata(string id) { if (m_Cache != null) diff --git a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs index 677169d76a..34df54a90b 100644 --- a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs @@ -116,6 +116,20 @@ namespace OpenSim.Services.Connectors return null; } + public AssetBase GetCached(string id) + { + string url = string.Empty; + string assetID = string.Empty; + + if (StringToUrlAndAssetID(id, out url, out assetID)) + { + IAssetService connector = GetConnector(url); + return connector.GetCached(assetID); + } + + return null; + } + public AssetMetadata GetMetadata(string id) { string url = string.Empty; diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs index 36c51c3075..79e49a11b9 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs @@ -123,6 +123,14 @@ namespace OpenSim.Services.Connectors.SimianGrid return GetRemote(id); } + public AssetBase GetCached(string id) + { + if (m_cache != null) + return m_cache.Get(id); + + return null; + } + /// /// Get an asset's metadata /// diff --git a/OpenSim/Services/Interfaces/IAssetService.cs b/OpenSim/Services/Interfaces/IAssetService.cs index f8bedfe1a3..3be6815728 100644 --- a/OpenSim/Services/Interfaces/IAssetService.cs +++ b/OpenSim/Services/Interfaces/IAssetService.cs @@ -50,6 +50,13 @@ namespace OpenSim.Services.Interfaces byte[] GetData(string id); + /// + /// Synchronously fetches an asset from the local cache only + /// + /// Asset ID + /// The fetched asset, or null if it did not exist in the local cache + AssetBase GetCached(string id); + /// /// Get an asset synchronously or asynchronously (depending on whether /// it is locally cached) and fire a callback with the fetched asset diff --git a/OpenSim/Tests/Common/Mock/MockAssetService.cs b/OpenSim/Tests/Common/Mock/MockAssetService.cs index cb380431d4..4118308bed 100644 --- a/OpenSim/Tests/Common/Mock/MockAssetService.cs +++ b/OpenSim/Tests/Common/Mock/MockAssetService.cs @@ -65,6 +65,11 @@ namespace OpenSim.Tests.Common.Mock return asset; } + public AssetBase GetCached(string id) + { + return Get(id); + } + public AssetMetadata GetMetadata(string id) { throw new System.NotImplementedException(); From 56c176f0a3b7d2543eeb35444da70ce4a343b5c5 Mon Sep 17 00:00:00 2001 From: dahlia Date: Fri, 9 Apr 2010 19:59:58 -0700 Subject: [PATCH 09/35] minor - add some documentation to PrimitiveBaseShape constructor with OpenMetaverse.Primitive parameter --- OpenSim/Framework/PrimitiveBaseShape.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs index 9c2a4f9ac1..9d294801e2 100644 --- a/OpenSim/Framework/PrimitiveBaseShape.cs +++ b/OpenSim/Framework/PrimitiveBaseShape.cs @@ -188,6 +188,10 @@ namespace OpenSim.Framework m_textureEntry = DEFAULT_TEXTURE; } + /// + /// Construct a PrimitiveBaseShape object from a OpenMetaverse.Primitive object + /// + /// public PrimitiveBaseShape(Primitive prim) { PCode = (byte)prim.PrimData.PCode; From 3d0860ae616749518a40c6f6088d2644d589daf9 Mon Sep 17 00:00:00 2001 From: dahlia Date: Mon, 12 Apr 2010 17:10:51 -0700 Subject: [PATCH 10/35] thanks lkalif for Mantis #4676 - a patch that adds support for inventory links Signed-off-by: dahlia --- CONTRIBUTORS.txt | 1 + .../Client/MXP/ClientStack/MXPClientView.cs | 1 + .../ClientStack/SirikataClientView.cs | 1 + .../VWoHTTP/ClientStack/VWHClientView.cs | 1 + OpenSim/Framework/IClientAPI.cs | 5 +++ .../ClientStack/LindenUDP/LLClientView.cs | 34 +++++++++++++++++++ .../Examples/SimpleModule/MyNpcCharacter.cs | 1 + .../Framework/Scenes/Scene.Inventory.cs | 31 +++++++++++++++++ OpenSim/Region/Framework/Scenes/Scene.cs | 1 + .../Server/IRCClientView.cs | 1 + .../OptionalModules/World/NPC/NPCAvatar.cs | 1 + OpenSim/Tests/Common/Mock/TestClient.cs | 1 + 12 files changed, 79 insertions(+) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index e5c8cb97e8..9aadd70927 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -88,6 +88,7 @@ what it is today. * Kitto Flora * KittyLiu * Kurt Taylor (IBM) +* lkalif * lulurun * M.Igarashi * maimedleech diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs index 17bd7959c7..1d6d4c1d03 100644 --- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs +++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs @@ -642,6 +642,7 @@ namespace OpenSim.Client.MXP.ClientStack public event Action OnRemoveAvatar; public event ObjectPermissions OnObjectPermissions; public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event LinkInventoryItem OnLinkInventoryItem; public event CreateInventoryFolder OnCreateNewInventoryFolder; public event UpdateInventoryFolder OnUpdateInventoryFolder; public event MoveInventoryFolder OnMoveInventoryFolder; diff --git a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs index 4ecbaf917f..43c64e9584 100644 --- a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs +++ b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs @@ -288,6 +288,7 @@ namespace OpenSim.Client.Sirikata.ClientStack public event Action OnRemoveAvatar; public event ObjectPermissions OnObjectPermissions; public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event LinkInventoryItem OnLinkInventoryItem; public event CreateInventoryFolder OnCreateNewInventoryFolder; public event UpdateInventoryFolder OnUpdateInventoryFolder; public event MoveInventoryFolder OnMoveInventoryFolder; diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs index 1da746ad2b..864b4f16f3 100644 --- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs +++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs @@ -291,6 +291,7 @@ namespace OpenSim.Client.VWoHTTP.ClientStack public event Action OnRemoveAvatar = delegate { }; public event ObjectPermissions OnObjectPermissions = delegate { }; public event CreateNewInventoryItem OnCreateNewInventoryItem = delegate { }; + public event LinkInventoryItem OnLinkInventoryItem = delegate { }; public event CreateInventoryFolder OnCreateNewInventoryFolder = delegate { }; public event UpdateInventoryFolder OnUpdateInventoryFolder = delegate { }; public event MoveInventoryFolder OnMoveInventoryFolder = delegate { }; diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 4577758a34..af88c4a632 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -236,6 +236,10 @@ namespace OpenSim.Framework IClientAPI remoteClient, UUID transActionID, UUID folderID, uint callbackID, string description, string name, sbyte invType, sbyte type, byte wearableType, uint nextOwnerMask, int creationDate); + public delegate void LinkInventoryItem( + IClientAPI remoteClient, UUID transActionID, UUID folderID, uint callbackID, string description, string name, + sbyte invType, sbyte type, UUID olditemID); + public delegate void FetchInventoryDescendents( IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder); @@ -930,6 +934,7 @@ namespace OpenSim.Framework event ObjectPermissions OnObjectPermissions; event CreateNewInventoryItem OnCreateNewInventoryItem; + event LinkInventoryItem OnLinkInventoryItem; event CreateInventoryFolder OnCreateNewInventoryFolder; event UpdateInventoryFolder OnUpdateInventoryFolder; event MoveInventoryFolder OnMoveInventoryFolder; diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 51ab281cad..f0f3932564 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -182,6 +182,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event TeleportLocationRequest OnSetStartLocationRequest; public event UpdateAvatarProperties OnUpdateAvatarProperties; public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event LinkInventoryItem OnLinkInventoryItem; public event CreateInventoryFolder OnCreateNewInventoryFolder; public event UpdateInventoryFolder OnUpdateInventoryFolder; public event MoveInventoryFolder OnMoveInventoryFolder; @@ -4749,6 +4750,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.UpdateInventoryFolder, HandleUpdateInventoryFolder); AddLocalPacketHandler(PacketType.MoveInventoryFolder, HandleMoveInventoryFolder); AddLocalPacketHandler(PacketType.CreateInventoryItem, HandleCreateInventoryItem); + AddLocalPacketHandler(PacketType.LinkInventoryItem, HandleLinkInventoryItem); AddLocalPacketHandler(PacketType.FetchInventory, HandleFetchInventory); AddLocalPacketHandler(PacketType.FetchInventoryDescendents, HandleFetchInventoryDescendents); AddLocalPacketHandler(PacketType.PurgeInventoryDescendents, HandlePurgeInventoryDescendents); @@ -7348,6 +7350,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } + private bool HandleLinkInventoryItem(IClientAPI sender, Packet Pack) + { + LinkInventoryItemPacket createLink = (LinkInventoryItemPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (createLink.AgentData.SessionID != SessionId || + createLink.AgentData.AgentID != AgentId) + return true; + } + #endregion + + LinkInventoryItem linkInventoryItem = OnLinkInventoryItem; + + if (linkInventoryItem != null) + { + linkInventoryItem( + this, + createLink.InventoryBlock.TransactionID, + createLink.InventoryBlock.FolderID, + createLink.InventoryBlock.CallbackID, + Util.FieldToString(createLink.InventoryBlock.Description), + Util.FieldToString(createLink.InventoryBlock.Name), + createLink.InventoryBlock.InvType, + createLink.InventoryBlock.Type, + createLink.InventoryBlock.OldItemID); + } + + return true; + } + private bool HandleFetchInventory(IClientAPI sender, Packet Pack) { if (OnFetchInventory != null) diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 8d27f9cf29..09611af887 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -129,6 +129,7 @@ namespace OpenSim.Region.Examples.SimpleModule public event Action OnRemoveAvatar; public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event LinkInventoryItem OnLinkInventoryItem; public event CreateInventoryFolder OnCreateNewInventoryFolder; public event UpdateInventoryFolder OnUpdateInventoryFolder; public event MoveInventoryFolder OnMoveInventoryFolder; diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 3b7f38e575..7c68ef4eed 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -722,6 +722,37 @@ namespace OpenSim.Region.Framework.Scenes } } + private void HandleLinkInventoryItem(IClientAPI remoteClient, UUID transActionID, UUID folderID, + uint callbackID, string description, string name, + sbyte invType, sbyte type, UUID olditemID) + { + m_log.DebugFormat("[AGENT INVENTORY]: Received request to create inventory item link {0} in folder {1} pointing to {2}", name, folderID, olditemID); + + if (!Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) + return; + + ScenePresence presence; + if (TryGetScenePresence(remoteClient.AgentId, out presence)) + { + byte[] data = null; + + AssetBase asset = new AssetBase(); + asset.FullID = olditemID; + asset.Type = type; + asset.Name = name; + asset.Description = description; + + CreateNewInventoryItem(remoteClient, remoteClient.AgentId.ToString(), folderID, name, 0, callbackID, asset, invType, (uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All, Util.UnixTimeSinceEpoch()); + + } + else + { + m_log.ErrorFormat( + "ScenePresence for agent uuid {0} unexpectedly not found in HandleLinkInventoryItem", + remoteClient.AgentId); + } + } + /// /// Remove an inventory item for the client's inventory /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index fc915a38b4..685a678023 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2749,6 +2749,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual void SubscribeToClientInventoryEvents(IClientAPI client) { client.OnCreateNewInventoryItem += CreateNewInventoryItem; + client.OnLinkInventoryItem += HandleLinkInventoryItem; client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder; client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder; client.OnMoveInventoryFolder += HandleMoveInventoryFolder; // 2; //!! diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index f5b148f69d..69e78b36ca 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -724,6 +724,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public event Action OnRemoveAvatar; public event ObjectPermissions OnObjectPermissions; public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event LinkInventoryItem OnLinkInventoryItem; public event CreateInventoryFolder OnCreateNewInventoryFolder; public event UpdateInventoryFolder OnUpdateInventoryFolder; public event MoveInventoryFolder OnMoveInventoryFolder; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 338c04b271..6360c9918d 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -235,6 +235,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC public event Action OnRemoveAvatar; public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event LinkInventoryItem OnLinkInventoryItem; public event CreateInventoryFolder OnCreateNewInventoryFolder; public event UpdateInventoryFolder OnUpdateInventoryFolder; public event MoveInventoryFolder OnMoveInventoryFolder; diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index f015db2c84..b07a0727a3 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -141,6 +141,7 @@ namespace OpenSim.Tests.Common.Mock public event Action OnRemoveAvatar; public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event LinkInventoryItem OnLinkInventoryItem; public event CreateInventoryFolder OnCreateNewInventoryFolder; public event UpdateInventoryFolder OnUpdateInventoryFolder; public event MoveInventoryFolder OnMoveInventoryFolder; From 54a5b6f4344275342177f6b3c9a2662909dd763a Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 12 Apr 2010 12:36:06 -0700 Subject: [PATCH 11/35] Reduce number of AvatarAnimations sent with large number of avatars --- .../Scenes/Animation/ScenePresenceAnimator.cs | 13 +++++++------ OpenSim/Region/Framework/Scenes/ScenePresence.cs | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 7307662b2a..de4c5fb053 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -419,11 +419,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation if (m_scenePresence.IsChildAgent) return; - m_scenePresence.Scene.ForEachScenePresence( - delegate(ScenePresence SP) - { - SP.Animator.SendAnimPack(); - }); + UUID[] animIDs; + int[] sequenceNums; + UUID[] objectIDs; + + m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); + client.SendAnimations(animIDs, sequenceNums, m_scenePresence.ControllingClient.AgentId, objectIDs); } /// @@ -451,4 +452,4 @@ namespace OpenSim.Region.Framework.Scenes.Animation m_scenePresence = null; } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index b5f621721a..3efb45fa87 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -912,6 +912,7 @@ namespace OpenSim.Region.Framework.Scenes m_isChildAgent = false; + // send the animations of the other presences to me m_scene.ForEachScenePresence(delegate(ScenePresence presence) { if (presence != this) From 6892fc41f71a00327336dec7158f3ce809ce32a4 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Tue, 13 Apr 2010 18:59:05 -0700 Subject: [PATCH 12/35] Applying patch from lkalif to add support for inventory links to the SimianGrid connectors --- OpenSim/Framework/SLUtil.cs | 33 +++++++++++++++++++ .../SimianInventoryServiceConnector.cs | 12 +++++++ 2 files changed, 45 insertions(+) diff --git a/OpenSim/Framework/SLUtil.cs b/OpenSim/Framework/SLUtil.cs index f6d6a7cf60..a4898061da 100644 --- a/OpenSim/Framework/SLUtil.cs +++ b/OpenSim/Framework/SLUtil.cs @@ -106,6 +106,39 @@ namespace OpenSim.Framework } } + public static string SLInvTypeToContentType(int invType) + { + switch ((InventoryType)invType) + { + case InventoryType.Animation: + return "application/vnd.ll.animation"; + case InventoryType.CallingCard: + return "application/vnd.ll.callingcard"; + case InventoryType.Folder: + return "application/vnd.ll.folder"; + case InventoryType.Gesture: + return "application/vnd.ll.gesture"; + case InventoryType.Landmark: + return "application/vnd.ll.landmark"; + case InventoryType.LSL: + return "application/vnd.ll.lsltext"; + case InventoryType.Notecard: + return "application/vnd.ll.notecard"; + case InventoryType.Attachment: + case InventoryType.Object: + return "application/vnd.ll.primitive"; + case InventoryType.Sound: + return "application/ogg"; + case InventoryType.Snapshot: + case InventoryType.Texture: + return "image/x-j2c"; + case InventoryType.Wearable: + return "application/vnd.ll.clothing"; + default: + return "application/octet-stream"; + } + } + public static sbyte ContentTypeToSLAssetType(string contentType) { switch (contentType) diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs index 56e74755bb..9005e947fd 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs @@ -583,6 +583,14 @@ namespace OpenSim.Services.Connectors.SimianGrid { "Permissions", permissions } }; + // Add different asset type only if it differs from inventory type + // (needed for links) + string invContentType = SLUtil.SLInvTypeToContentType(item.InvType); + string assetContentType = SLUtil.SLAssetTypeToContentType(item.AssetType); + + if (invContentType != assetContentType) + extraData["LinkedItemType"] = OSD.FromString(assetContentType); + NameValueCollection requestArgs = new NameValueCollection { { "RequestMethod", "AddInventoryItem" }, @@ -593,6 +601,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "Name", item.Name }, { "Description", item.Description }, { "CreatorID", item.CreatorId }, + { "ContentType", invContentType }, { "ExtraData", OSDParser.SerializeJsonString(extraData) } }; @@ -781,6 +790,9 @@ namespace OpenSim.Services.Connectors.SimianGrid invItem.GroupPermissions = perms["GroupMask"].AsUInteger(); invItem.NextPermissions = perms["NextOwnerMask"].AsUInteger(); } + + if (extraData.ContainsKey("LinkedItemType")) + invItem.AssetType = extraData["LinkedItemType"].AsInteger(); } if (invItem.BasePermissions == 0) From bdc03dbff958459d0e2fd96045a859455293bf37 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 14 Apr 2010 10:36:03 -0700 Subject: [PATCH 13/35] * Added 32bitLauncher for Robust. Still need to test it on a 64 bit machine. * PrimitiveBaseShape wants to be be committed too -- EOF. --- OpenSim/Framework/PrimitiveBaseShape.cs | 6 +- OpenSim/Server/ServerMain.cs | 2 +- OpenSim/Tools/Robust.32BitLaunch/Program.cs | 60 +++++++++++++++++ .../Properties/AssemblyInfo.cs | 63 ++++++++++++++++++ .../Robust.32BitLaunch/Robust.32BitLaunch.sln | 20 ++++++ bin/Robust.32BitLaunch.exe | Bin 0 -> 5632 bytes bin/Robust.32BitLaunch.exe.config | 32 +++++++++ 7 files changed, 179 insertions(+), 4 deletions(-) create mode 100644 OpenSim/Tools/Robust.32BitLaunch/Program.cs create mode 100644 OpenSim/Tools/Robust.32BitLaunch/Properties/AssemblyInfo.cs create mode 100644 OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.sln create mode 100644 bin/Robust.32BitLaunch.exe create mode 100644 bin/Robust.32BitLaunch.exe.config diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs index 9d294801e2..1208b97300 100644 --- a/OpenSim/Framework/PrimitiveBaseShape.cs +++ b/OpenSim/Framework/PrimitiveBaseShape.cs @@ -188,9 +188,9 @@ namespace OpenSim.Framework m_textureEntry = DEFAULT_TEXTURE; } - /// - /// Construct a PrimitiveBaseShape object from a OpenMetaverse.Primitive object - /// + /// + /// Construct a PrimitiveBaseShape object from a OpenMetaverse.Primitive object + /// /// public PrimitiveBaseShape(Primitive prim) { diff --git a/OpenSim/Server/ServerMain.cs b/OpenSim/Server/ServerMain.cs index 10cd9c5b89..d3e65a4bdd 100644 --- a/OpenSim/Server/ServerMain.cs +++ b/OpenSim/Server/ServerMain.cs @@ -47,7 +47,7 @@ namespace OpenSim.Server protected static List m_ServiceConnectors = new List(); - static int Main(string[] args) + public static int Main(string[] args) { m_Server = new HttpServerBase("R.O.B.U.S.T.", args); diff --git a/OpenSim/Tools/Robust.32BitLaunch/Program.cs b/OpenSim/Tools/Robust.32BitLaunch/Program.cs new file mode 100644 index 0000000000..490414c456 --- /dev/null +++ b/OpenSim/Tools/Robust.32BitLaunch/Program.cs @@ -0,0 +1,60 @@ +/* + * 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 log4net; + +namespace Robust._32BitLaunch +{ + class Program + { + static void Main(string[] args) + { + log4net.Config.XmlConfigurator.Configure(); + + System.Console.WriteLine("32-bit OpenSim executor"); + System.Console.WriteLine("-----------------------"); + System.Console.WriteLine(""); + System.Console.WriteLine("This application is compiled for 32-bit CPU and will run under WOW32 or similar."); + System.Console.WriteLine("All 64-bit incompatibilities should be gone."); + System.Console.WriteLine(""); + System.Threading.Thread.Sleep(300); + try + { + global::OpenSim.Server.OpenSimServer.Main(args); + } + catch (Exception ex) + { + System.Console.WriteLine("OpenSim threw an exception:"); + System.Console.WriteLine(ex.ToString()); + System.Console.WriteLine(""); + System.Console.WriteLine("Application will now terminate!"); + System.Console.WriteLine(""); + } + } + } +} diff --git a/OpenSim/Tools/Robust.32BitLaunch/Properties/AssemblyInfo.cs b/OpenSim/Tools/Robust.32BitLaunch/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..cf80f472ef --- /dev/null +++ b/OpenSim/Tools/Robust.32BitLaunch/Properties/AssemblyInfo.cs @@ -0,0 +1,63 @@ +/* + * 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Robust.32BitLaunch")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("http://opensimulator.org")] +[assembly: AssemblyProduct("Robust.32BitLaunch")] +[assembly: AssemblyCopyright("Copyright (c) 2008")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("5072e919-46ab-47e6-8a63-08108324ccdf")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("0.6.3.*")] +[assembly: AssemblyVersion("0.6.3.*")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.sln b/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.sln new file mode 100644 index 0000000000..c7c97b1d93 --- /dev/null +++ b/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C# Express 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Robust.32BitLaunch", "Robust.32BitLaunch.csproj", "{595D67F3-B413-4A43-8568-5B5930E3B31D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {595D67F3-B413-4A43-8568-5B5930E3B31D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {595D67F3-B413-4A43-8568-5B5930E3B31D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {595D67F3-B413-4A43-8568-5B5930E3B31D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {595D67F3-B413-4A43-8568-5B5930E3B31D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/bin/Robust.32BitLaunch.exe b/bin/Robust.32BitLaunch.exe new file mode 100644 index 0000000000000000000000000000000000000000..3119dc966e43aa93a26ae3c205b4675143755cdb GIT binary patch literal 5632 zcmeHLU2Ggz6+W|e9LH&_IHmbfXgc16$_{vT{ezP@akKu(j}xah-gTTHOY!XN^?H)| z>zx_Lrll+bDykMJZ>_`w5j+(7f)ElFEh-2hk%#br`cNTJ6_8K`NP#C%K!oqy*D%Pss7^$WcEf_MC z7Dmdq9FP_~?RXkm4&ED5I6ee9Wwd~YZG8k!L(373HVhTIzN8kNDaW({&a3a*ZwPw0G$+Y4C;UJZ&q`;BL5gAl3Be;#aX5j;8zs< zu7Woe{GEdTP;j@#GQA4g+BvO-KC9phit=p*-`0Mr9jEs(Q48%!{S7il0NdzusUX!t zucUacH&d^r+UcFtO;B!w!i_y+$o)=ioo-}|N7FjfzfJ|^@!!?xxxJSmlf-w0I_NUC z=RO5H73@~9SHWWnjwm>x;HLmtnzc*?Z3UkKJV2iZJVeg}?!>HLOZCw!bR#uLH|S@n zzrFc#vG+A6N8#>|ukBEBbi_^YkrHEV>1FjeZRn z((eJEra#j;YOWAk3s$LVlrf@N1j@12nnuG4)j;J}o?AC9HHsuey17O>altRej(CD* z{9+tNMt|R^9Zj0CXDu0GMbLCoX>05&4SaG#%a@K_r2J|a374jdSA`YP1=IG(up(cQ zDY1nUt}!DP9k6ZRqmeKaZqZpS*pVYfB5d_y9Em!4T!fai0~X!L9P_I+X`u16ytK)TsKuhLq)-I z!<&1Yg>wOn%SLZOP$`}fj=7?+aLw15Budr;t7toR)R6LxTZtUMJm86_)*Hzx(k0hf zTTkql+CVTC`i`JEX-8tx_C(F+!jcqb36W5OQQi?Eps7H3dD}HO1R-m~>Zsr+<&;jX zSVHY9^&({YsgHW7NH#^JYZ^NVslQxWcpeI}lBNu!d5&}h4r$sfXPV1cO=NI1&&7?xl| z0-r-rbIO8VwH89&RXQdl4AL%-U`Ey-q=ANH*sxObDe;!m#NM;#LPZoJHXrjj%9A3f zItm#_CD`(jdlMQ#UV?WWa;EZ?Q*40})blY!baLcAnOck0!z^qig058Ycq*rY?-p0z zkH7ln%v)zFe|qNH_lw&eqt+jOX8z*7f%l%r$)P>k-lUV(tZQ03gVYv)j$uYyTlbIu z_U*?zE_LE0)S8JU09v8dsjE^lD+HQ>Z z$d`sM%S5bOuQz&^)vfnsvqw>;H9EvM0&%SOSkJ(qS?n1&A_jYonuGm4*`vMLqy2pY zmQ`9*hyB)G+#m46?T<@6Hz3I+_5dG^h1BjjX$DXFUVXpgUGcAn%ES6Sm{p&_^D6G0 zuWl!r$&cs1@Ykoe|Kg2bp8fK#^xxd=zw;Vvj1A3~#PWPKoSw2B^`P#H8ezWr>dhB? z-wEe8re@wRUY$o75oRbhVH-iINR!n&BBmpcah$zFd6gKy^W zxsqIN6BaJce@xhFywEg&{vzuB6~I$818f3?^GS>+08azw_T%Q;|4QzoHRYr~skq7a zVU1HI5#P}@Smk1SS`|LRnve)d-v+%HZb%;}bABB)G7%H+=RP z3ZjCcP2*0h)qNO;Mu;NLzO9vUmYac25ywLa8-_ZBMj;c?B&_lwW#KsBmPPGavv*OI zboPJ`5^lZF&ek8Ee-Gq2i%I$C((g1x^&s;an1xSwZj&mWNsP+M5@#zwo;ad1eB^KF zjWnIQ5J5NTxI=K>v6Im*Dc`25y1ZKKTW#felw|&c`gm6PI1Rf#4%-+rM-34_c&-Oj zuGibSH{%_?w z*U@n?6J{!_r!2|RfOr2PwZ$rVOBpCbQti$ z;dCs$q0m~wtvu{;ZA<#0zsTp2J7k8gvD};1UDLA{MHp4D%E@dnrR#NL6D5ILdbGOE zBR*2ox@WqW{=(`=5IDA_?!AT?1nEp-A(Hq=n(!9=2lS^et@JQ=D6ANF+12V86e*sH z;io7~OM4mD@3IIV&}x6ps*bj12S=b4^JmedSQd`%FdR;s;e@yBUlTH|$M%SYj}fGC x(R4yl4N4iwY~oGL^~^foPh{#zfWV1NZG|vUufRs2C;#`T;BNO}`~S + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + From 1e87fc8a26af3eb8029efa61d711935ff2f337b8 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Wed, 14 Apr 2010 11:05:28 -0700 Subject: [PATCH 14/35] Applying a patch from lkalif to fix a small bug in the previous patch --- .../Connectors/SimianGrid/SimianInventoryServiceConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs index 9005e947fd..dc68259d93 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs @@ -792,7 +792,7 @@ namespace OpenSim.Services.Connectors.SimianGrid } if (extraData.ContainsKey("LinkedItemType")) - invItem.AssetType = extraData["LinkedItemType"].AsInteger(); + invItem.AssetType = SLUtil.ContentTypeToSLAssetType(extraData["LinkedItemType"].AsString()); } if (invItem.BasePermissions == 0) From e0f8362e7a24a842a569b692652bc18784a2248b Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 14 Apr 2010 22:31:11 +0100 Subject: [PATCH 15/35] minor: add some documentation around the asset udp request path and replace some magic numbers with libomv enums --- OpenSim/Data/SQLite/SQLiteAssetData.cs | 2 +- .../ClientStack/LindenUDP/LLClientView.cs | 51 ++++++++++++------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/OpenSim/Data/SQLite/SQLiteAssetData.cs b/OpenSim/Data/SQLite/SQLiteAssetData.cs index ace40e5a0c..a032670588 100644 --- a/OpenSim/Data/SQLite/SQLiteAssetData.cs +++ b/OpenSim/Data/SQLite/SQLiteAssetData.cs @@ -137,7 +137,7 @@ namespace OpenSim.Data.SQLite cmd.Parameters.Add(new SqliteParameter(":Local", asset.Local)); cmd.Parameters.Add(new SqliteParameter(":Temporary", asset.Temporary)); cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); - + cmd.ExecuteNonQuery(); } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index f0f3932564..b3f5f09c04 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -7069,6 +7069,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } + /// + /// This is the entry point for the UDP route by which the client can retrieve asset data. If the request + /// is successful then a TransferInfo packet will be sent back, followed by one or more TransferPackets + /// + /// + /// + /// This parameter may be ignored since we appear to return true whatever happens private bool HandleTransferRequest(IClientAPI sender, Packet Pack) { //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request"); @@ -7079,7 +7086,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Has to be done here, because AssetCache can't do it // UUID taskID = UUID.Zero; - if (transfer.TransferInfo.SourceType == 3) + if (transfer.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) { taskID = new UUID(transfer.TransferInfo.Params, 48); UUID itemID = new UUID(transfer.TransferInfo.Params, 64); @@ -11356,17 +11363,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP return String.Empty; } - public void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID) + /// + /// Make an asset request to the asset service in response to a client request. + /// + /// + /// + protected void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID) { UUID requestID = UUID.Zero; - if (transferRequest.TransferInfo.SourceType == 2) + if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) { - //direct asset request requestID = new UUID(transferRequest.TransferInfo.Params, 0); } - else if (transferRequest.TransferInfo.SourceType == 3) + else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) { - //inventory asset request requestID = new UUID(transferRequest.TransferInfo.Params, 80); //m_log.Debug("[XXX] inventory asset request " + requestID); //if (taskID == UUID.Zero) // Agent @@ -11379,29 +11389,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP // } } - //check to see if asset is in local cache, if not we need to request it from asset server. - //m_log.Debug("asset request " + requestID); + //m_log.DebugFormat("[LLCLIENTVIEW]: {0} requesting asset {1}", Name, requestID); m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); - } + /// + /// When we get a reply back from the asset service in response to a client request, send back the data. + /// + /// + /// + /// protected void AssetReceived(string id, Object sender, AssetBase asset) { TransferRequestPacket transferRequest = (TransferRequestPacket)sender; UUID requestID = UUID.Zero; - byte source = 2; - if ((transferRequest.TransferInfo.SourceType == 2) || (transferRequest.TransferInfo.SourceType == 2222)) + byte source = (byte)SourceType.Asset; + + if ((transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) + || (transferRequest.TransferInfo.SourceType == 2222)) { - //direct asset request requestID = new UUID(transferRequest.TransferInfo.Params, 0); } - else if ((transferRequest.TransferInfo.SourceType == 3) || (transferRequest.TransferInfo.SourceType == 3333)) + else if ((transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) + || (transferRequest.TransferInfo.SourceType == 3333)) { - //inventory asset request requestID = new UUID(transferRequest.TransferInfo.Params, 80); - source = 3; + source = (byte)SourceType.SimInventoryItem; //m_log.Debug("asset request " + requestID); } @@ -11414,9 +11429,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP if ((userAssets != string.Empty) && (userAssets != m_hyperAssets.GetSimAssetServer())) { m_log.DebugFormat("[CLIENT]: asset {0} not found in local asset storage. Trying user's storage.", id); - if (transferRequest.TransferInfo.SourceType == 2) + if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) transferRequest.TransferInfo.SourceType = 2222; // marker - else if (transferRequest.TransferInfo.SourceType == 3) + else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) transferRequest.TransferInfo.SourceType = 3333; // marker m_assetService.Get(userAssets + "/" + id, transferRequest, AssetReceived); @@ -11431,7 +11446,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } // Scripts cannot be retrieved by direct request - if (transferRequest.TransferInfo.SourceType == 2 && asset.Type == 10) + if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset && asset.Type == 10) return; // The asset is known to exist and is in our cache, so add it to the AssetRequests list From 407b48f3bb20b643c694c725bbf94a02e73d9fd6 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 14 Apr 2010 19:22:48 -0700 Subject: [PATCH 16/35] The missing .csproj for the Robust 32 bit launcher --- .../Robust.32BitLaunch.csproj | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.csproj diff --git a/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.csproj b/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.csproj new file mode 100644 index 0000000000..f19e082c28 --- /dev/null +++ b/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.csproj @@ -0,0 +1,62 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {595D67F3-B413-4A43-8568-5B5930E3B31D} + Exe + Properties + Robust._32BitLaunch + Robust.32BitLaunch + v3.5 + 512 + + + true + full + false + ..\..\..\bin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\..\..\bin\log4net.dll + + + False + ..\..\..\bin\OpenSim.Server.exe + + + + 3.5 + + + + + + + + + + + \ No newline at end of file From a7aab6af0cc82566e52cacc3c118ee2468a12c8a Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 14 Apr 2010 19:39:27 -0700 Subject: [PATCH 17/35] This version of the launcher exe works. --- bin/Robust.32BitLaunch.exe | Bin 5632 -> 5632 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/bin/Robust.32BitLaunch.exe b/bin/Robust.32BitLaunch.exe index 3119dc966e43aa93a26ae3c205b4675143755cdb..14a6db3f1f70a6b5767aeede7a5520821301b606 100644 GIT binary patch delta 957 zcmZ8g-%Ha`6#v}&-4ET?a=ElDZF8n$TQZ%5C6ejVnq<*7!I-(3Q&#HaJ2ga5tA`99 za$JZc3Zh;NBWwKu)k9BF27y6fZ@!fUB0*A}@2o94aL)alANQPd&%JlbHRYO}mL8A2 zO3oDX5@+&ZyK%_@w1TJs_^M7?^9^CZK)RhAdxe#|LqID1|*=$pCIQ z(^`&|ddeKmL~G(Z$(*h-2|2q}zLg32$BGqzj>z(;Qv{&zLVY2rCEQ*>SsaaiUn5h_ zM5K&kw5HNs>2Z6i4k;Ej`bjo$z%~Ia(CVTQ*!;tCY_Kmu2>75Trv0{{AB$Q*sbgyi zp77H8ob-T*NX7g1dqCxsGE|&Ky2Xl4W*EgCDOUTDy`8qp-JrtsWk2|;q7f9;x zl;0=(nm3bujjwPc^wK6-N+nUNa&d!I^s3Ie%@{)mN^qTI8ImOPFo&1C8u##?AH+O1 zcpaY5AR3U1-IDmCYO5$^l^BPUG+6P1y$d|5%jG_|7=ooZ{rZKe1BXp^UI zs^2j2S(8)L9+eZZ_#ll3fr#7}9d4E*1JO%y`C`hiZDOgpoMo1`+WKhe=k{LT?D)55 z9rM~7VoGOYN5uo3gLR6xx|x$L3`Lb~#{!wnu0MI}mHS}`7|j`%H66!A@13RoMWnDgM_8y^L?yVqS zvk^9BV~2HybR}^Iqf0H>SyubsoDHa8BnId}c^AS*NpKbSI)z>5oCx^?{DNkny^Kr0mt}HWkA zxee=lg_s>KB6=U+b%}!hmRg1T=s`6ek+-9WCp?5X%=0kj@t!x~1-j5oayGfJDOcTJ z;m0Vx;R^HxQb411(6vYebdxqNCKdPbA*u2oTOm$+qpUJ*$rxe`+IHDzX1~2P@_0G& zwym%|cIS1x{IpmzdDsQ9Yf@Q{@R+BSGDhzf`{v*^+QkkzQ_dcvvp`$7U Date: Wed, 14 Apr 2010 19:48:40 -0700 Subject: [PATCH 18/35] Patch from mcortez to add basic caching to the groups module. This prevents database/network explosions when you have a significant number of group-owned prims in a scene --- .../SimianGroupsServicesConnectorModule.cs | 81 +++++++++-- .../XmlRpcGroupsServicesConnectorModule.cs | 133 ++++++++++++------ 2 files changed, 161 insertions(+), 53 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs index 669373f125..9363205263 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs @@ -167,6 +167,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private bool m_debugEnabled = false; + private ExpiringCache m_memoryCache; + private int m_cacheTimeout = 30; + // private IUserAccountService m_accountService = null; @@ -203,7 +206,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; } - m_log.InfoFormat("[GROUPS-CONNECTOR]: Initializing {0}", this.Name); + m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Initializing {0}", this.Name); m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); if ((m_groupsServerURI == null) || @@ -214,6 +217,22 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; } + + m_cacheTimeout = groupsConfig.GetInt("GroupsCacheTimeout", 30); + if (m_cacheTimeout == 0) + { + m_log.WarnFormat("[SIMIAN-GROUPS-CONNECTOR] Groups Cache Disabled."); + } + else + { + m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Groups Cache Timeout set to {0}.", m_cacheTimeout); + } + + + + m_memoryCache = new ExpiringCache(); + + // If we got all the config options we need, lets start'er'up m_connectorEnabled = true; @@ -224,7 +243,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void Close() { - m_log.InfoFormat("[GROUPS-CONNECTOR]: Closing {0}", this.Name); + m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Closing {0}", this.Name); } public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene) @@ -657,7 +676,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups }; - OSDMap response = WebUtil.PostToService(m_groupsServerURI, requestArgs); + OSDMap response = CachedPostRequest(requestArgs); if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) { OSDArray entryArray = (OSDArray)response["Entries"]; @@ -1086,7 +1105,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups }; - OSDMap Response = WebUtil.PostToService(m_groupsServerURI, RequestArgs); + OSDMap Response = CachedPostRequest(RequestArgs); if (Response["Success"].AsBoolean()) { return true; @@ -1113,7 +1132,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups }; - OSDMap Response = WebUtil.PostToService(m_groupsServerURI, RequestArgs); + OSDMap Response = CachedPostRequest(RequestArgs); if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) { OSDArray entryArray = (OSDArray)Response["Entries"]; @@ -1153,7 +1172,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups }; - OSDMap Response = WebUtil.PostToService(m_groupsServerURI, RequestArgs); + OSDMap Response = CachedPostRequest(RequestArgs); if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) { OSDArray entryArray = (OSDArray)Response["Entries"]; @@ -1194,7 +1213,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups }; - OSDMap Response = WebUtil.PostToService(m_groupsServerURI, RequestArgs); + OSDMap Response = CachedPostRequest(RequestArgs); if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) { OSDArray entryArray = (OSDArray)Response["Entries"]; @@ -1234,7 +1253,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups - OSDMap response = WebUtil.PostToService(m_groupsServerURI, requestArgs); + OSDMap response = CachedPostRequest(requestArgs); if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) { maps = new Dictionary(); @@ -1272,7 +1291,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups - OSDMap response = WebUtil.PostToService(m_groupsServerURI, requestArgs); + OSDMap response = CachedPostRequest(requestArgs); if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) { maps = new Dictionary(); @@ -1310,7 +1329,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups }; - OSDMap response = WebUtil.PostToService(m_groupsServerURI, requestArgs); + OSDMap response = CachedPostRequest(requestArgs); if (response["Success"].AsBoolean()) { return true; @@ -1323,6 +1342,48 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } #endregion + #region CheesyCache + OSDMap CachedPostRequest(NameValueCollection requestArgs) + { + // Immediately forward the request if the cache is disabled. + if (m_cacheTimeout == 0) + { + return WebUtil.PostToService(m_groupsServerURI, requestArgs); + } + + // Check if this is an update or a request + if ( requestArgs["RequestMethod"] == "RemoveGeneric" + || requestArgs["RequestMethod"] == "AddGeneric" + ) + + { + // Any and all updates cause the cache to clear + m_memoryCache.Clear(); + + // Send update to server, return the response without caching it + return WebUtil.PostToService(m_groupsServerURI, requestArgs); + + } + + // If we're not doing an update, we must be requesting data + + // Create the cache key for the request and see if we have it cached + string CacheKey = WebUtil.BuildQueryString(requestArgs); + OSDMap response = null; + if (!m_memoryCache.TryGetValue(CacheKey, out response)) + { + // if it wasn't in the cache, pass the request to the Simian Grid Services + response = WebUtil.PostToService(m_groupsServerURI, requestArgs); + + // and cache the response + m_memoryCache.AddOrUpdate(CacheKey, response, TimeSpan.FromSeconds(m_cacheTimeout)); + } + + // return cached response + return response; + } + #endregion + } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index 523dfbe356..e7967d1b49 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -29,6 +29,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Reflection; +using System.Text; using Nwc.XmlRpc; @@ -70,6 +71,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private IUserAccountService m_accountService = null; + private ExpiringCache m_memoryCache; + private int m_cacheTimeout = 30; + // Used to track which agents are have dropped from a group chat session // Should be reset per agent, on logon // TODO: move this to Flotsam XmlRpc Service @@ -111,7 +115,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; } - m_log.InfoFormat("[GROUPS-CONNECTOR]: Initializing {0}", this.Name); + m_log.InfoFormat("[XMLRPC-GROUPS-CONNECTOR]: Initializing {0}", this.Name); m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); if ((m_groupsServerURI == null) || @@ -127,7 +131,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_groupReadKey = groupsConfig.GetString("XmlRpcServiceReadKey", string.Empty); m_groupWriteKey = groupsConfig.GetString("XmlRpcServiceWriteKey", string.Empty); - + + m_cacheTimeout = groupsConfig.GetInt("GroupsCacheTimeout", 30); + if (m_cacheTimeout == 0) + { + m_log.WarnFormat("[XMLRPC-GROUPS-CONNECTOR]: Groups Cache Disabled."); + } + else + { + m_log.InfoFormat("[XMLRPC-GROUPS-CONNECTOR]: Groups Cache Timeout set to {0}.", m_cacheTimeout); + } // If we got all the config options we need, lets start'er'up @@ -137,7 +150,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void Close() { - m_log.InfoFormat("[GROUPS-CONNECTOR]: Closing {0}", this.Name); + m_log.InfoFormat("[XMLRPC-GROUPS-CONNECTOR]: Closing {0}", this.Name); } public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene) @@ -919,50 +932,84 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups ///
private Hashtable XmlRpcCall(UUID requestingAgentID, string function, Hashtable param) { - string UserService; - UUID SessionID; - GetClientGroupRequestID(requestingAgentID, out UserService, out SessionID); - param.Add("requestingAgentID", requestingAgentID.ToString()); - param.Add("RequestingAgentUserService", UserService); - param.Add("RequestingSessionID", SessionID.ToString()); - - - param.Add("ReadKey", m_groupReadKey); - param.Add("WriteKey", m_groupWriteKey); - - - IList parameters = new ArrayList(); - parameters.Add(param); - - ConfigurableKeepAliveXmlRpcRequest req; - req = new ConfigurableKeepAliveXmlRpcRequest(function, parameters, m_disableKeepAlive); - XmlRpcResponse resp = null; + string CacheKey = null; - try + // Only bother with the cache if it isn't disabled. + if (m_cacheTimeout > 0) { - resp = req.Send(m_groupsServerURI, 10000); + if (!function.StartsWith("groups.get")) + { + // Any and all updates cause the cache to clear + m_memoryCache.Clear(); + } + else + { + StringBuilder sb = new StringBuilder(requestingAgentID + function); + foreach (object key in param.Keys) + { + if (param[key] != null) + { + sb.AppendFormat(",{0}:{1}", key.ToString(), param[key].ToString()); + } + } + + CacheKey = sb.ToString(); + m_memoryCache.TryGetValue(CacheKey, out resp); + } + } - catch (Exception e) + + if( resp == null ) { - + string UserService; + UUID SessionID; + GetClientGroupRequestID(requestingAgentID, out UserService, out SessionID); + param.Add("requestingAgentID", requestingAgentID.ToString()); + param.Add("RequestingAgentUserService", UserService); + param.Add("RequestingSessionID", SessionID.ToString()); - m_log.ErrorFormat("[XMLRPCGROUPDATA]: An error has occured while attempting to access the XmlRpcGroups server method: {0}", function); - m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} ", e.ToString()); - foreach (string ResponseLine in req.RequestResponse.Split(new string[] { Environment.NewLine },StringSplitOptions.None)) + param.Add("ReadKey", m_groupReadKey); + param.Add("WriteKey", m_groupWriteKey); + + + IList parameters = new ArrayList(); + parameters.Add(param); + + ConfigurableKeepAliveXmlRpcRequest req; + req = new ConfigurableKeepAliveXmlRpcRequest(function, parameters, m_disableKeepAlive); + + + try { - m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} ", ResponseLine); - } + resp = req.Send(m_groupsServerURI, 10000); - foreach (string key in param.Keys) + if ((m_cacheTimeout > 0) && (CacheKey != null)) + { + m_memoryCache.AddOrUpdate(CacheKey, resp, TimeSpan.FromSeconds(m_cacheTimeout)); + } + + } + catch (Exception e) { - m_log.WarnFormat("[XMLRPCGROUPDATA]: {0} :: {1}", key, param[key].ToString()); - } + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: An error has occured while attempting to access the XmlRpcGroups server method: {0}", function); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} ", e.ToString()); - Hashtable respData = new Hashtable(); - respData.Add("error", e.ToString()); - return respData; + foreach (string ResponseLine in req.RequestResponse.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)) + { + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} ", ResponseLine); + } + + foreach (string key in param.Keys) + { + m_log.WarnFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} :: {1}", key, param[key].ToString()); + } + + Hashtable respData = new Hashtable(); + respData.Add("error", e.ToString()); + return respData; + } } if (resp.Value is Hashtable) @@ -976,21 +1023,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return respData; } - m_log.ErrorFormat("[XMLRPCGROUPDATA]: The XmlRpc server returned a {1} instead of a hashtable for {0}", function, resp.Value.GetType().ToString()); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: The XmlRpc server returned a {1} instead of a hashtable for {0}", function, resp.Value.GetType().ToString()); if (resp.Value is ArrayList) { ArrayList al = (ArrayList)resp.Value; - m_log.ErrorFormat("[XMLRPCGROUPDATA]: Contains {0} elements", al.Count); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Contains {0} elements", al.Count); foreach (object o in al) { - m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} :: {1}", o.GetType().ToString(), o.ToString()); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} :: {1}", o.GetType().ToString(), o.ToString()); } } else { - m_log.ErrorFormat("[XMLRPCGROUPDATA]: Function returned: {0}", resp.Value.ToString()); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Function returned: {0}", resp.Value.ToString()); } Hashtable error = new Hashtable(); @@ -1000,16 +1047,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private void LogRespDataToConsoleError(Hashtable respData) { - m_log.Error("[XMLRPCGROUPDATA]: Error:"); + m_log.Error("[XMLRPC-GROUPS-CONNECTOR]: Error:"); foreach (string key in respData.Keys) { - m_log.ErrorFormat("[XMLRPCGROUPDATA]: Key: {0}", key); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Key: {0}", key); string[] lines = respData[key].ToString().Split(new char[] { '\n' }); foreach (string line in lines) { - m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0}", line); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0}", line); } } From 48f37339636f52392f698ae6036f970183ccae91 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 16 Apr 2010 20:40:01 +0100 Subject: [PATCH 19/35] Fix http://opensimulator.org/mantis/view.php?id=4657 where OpenSim.Grid.UserServer.exe fails on startup if no previous config probably appears to occur because mono 2.4.2.3 (and possibly later) erroneously returns a value of 0 for BufferWidth and BufferHeight in some circumstances --- OpenSim/Framework/Console/LocalConsole.cs | 63 +++++++++++++++++------ OpenSim/Framework/Util.cs | 2 +- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/OpenSim/Framework/Console/LocalConsole.cs b/OpenSim/Framework/Console/LocalConsole.cs index be936b6671..a3036d0df6 100644 --- a/OpenSim/Framework/Console/LocalConsole.cs +++ b/OpenSim/Framework/Console/LocalConsole.cs @@ -38,7 +38,7 @@ namespace OpenSim.Framework.Console { /// /// A console that uses cursor control and color - /// + ///
public class LocalConsole : CommandConsole { // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -100,24 +100,40 @@ namespace OpenSim.Framework.Console private int SetCursorTop(int top) { // From at least mono 2.4.2.3, window resizing can give mono an invalid row and column values. If we try - // to set a cursor row position with a currently invalid column, mono will throw an exception. - // Therefore, we need to make sure that the column position is valid first. + // to set a cursor row position with a currently invalid column, mono will throw an exception. + // Therefore, we need to make sure that the column position is valid first. int left = System.Console.CursorLeft; if (left < 0) + { System.Console.CursorLeft = 0; - else if (left >= System.Console.BufferWidth) - System.Console.CursorLeft = System.Console.BufferWidth - 1; + } + else + { + int bw = System.Console.BufferWidth; + + // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657) + if (bw > 0 && left >= bw) + System.Console.CursorLeft = bw - 1; + } if (top < 0) + { top = 0; - if (top >= System.Console.BufferHeight) - top = System.Console.BufferHeight - 1; + } + else + { + int bh = System.Console.BufferHeight; + + // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657) + if (bh > 0 && top >= bh) + top = bh - 1; + } System.Console.CursorTop = top; return top; - } + } /// /// Set the cursor column. @@ -129,23 +145,38 @@ namespace OpenSim.Framework.Console /// /// /// The new cursor column. - /// + /// private int SetCursorLeft(int left) { // From at least mono 2.4.2.3, window resizing can give mono an invalid row and column values. If we try - // to set a cursor column position with a currently invalid row, mono will throw an exception. - // Therefore, we need to make sure that the row position is valid first. + // to set a cursor column position with a currently invalid row, mono will throw an exception. + // Therefore, we need to make sure that the row position is valid first. int top = System.Console.CursorTop; if (top < 0) + { System.Console.CursorTop = 0; - else if (top >= System.Console.BufferHeight) - System.Console.CursorTop = System.Console.BufferHeight - 1; + } + else + { + int bh = System.Console.BufferHeight; + // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657) + if (bh > 0 && top >= bh) + System.Console.CursorTop = bh - 1; + } if (left < 0) + { left = 0; - if (left >= System.Console.BufferWidth) - left = System.Console.BufferWidth - 1; + } + else + { + int bw = System.Console.BufferWidth; + + // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657) + if (bw > 0 && left >= bw) + left = bw - 1; + } System.Console.CursorLeft = left; @@ -183,7 +214,7 @@ namespace OpenSim.Framework.Console System.Console.Write("{0}", prompt); SetCursorTop(new_y); - SetCursorLeft(new_x); + SetCursorLeft(new_x); } } diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 64f6118cfc..802cb37aa0 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -1486,4 +1486,4 @@ namespace OpenSim.Framework } } -} +} \ No newline at end of file From 9131a0d4a4ec24e3216c65cdf4b00af79c07a046 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 16 Apr 2010 21:12:09 +0100 Subject: [PATCH 20/35] minor: stop datasnapshot issuing a warning log message if it's disabled --- OpenSim/Region/DataSnapshot/DataSnapshotManager.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs index 6949d7c2c7..9fc002b7b9 100644 --- a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs +++ b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs @@ -94,7 +94,7 @@ namespace OpenSim.Region.DataSnapshot if (!m_configLoaded) { m_configLoaded = true; - m_log.Info("[DATASNAPSHOT]: Loading configuration"); + //m_log.Debug("[DATASNAPSHOT]: Loading configuration"); //Read from the config for options lock (m_syncInit) { @@ -123,7 +123,7 @@ namespace OpenSim.Region.DataSnapshot } catch (Exception) { - m_log.Info("[DATASNAPSHOT]: Could not load configuration. DataSnapshot will be disabled."); + m_log.Warn("[DATASNAPSHOT]: Could not load configuration. DataSnapshot will be disabled."); m_enabled = false; return; } @@ -179,7 +179,7 @@ namespace OpenSim.Region.DataSnapshot } else { - m_log.Warn("[DATASNAPSHOT]: Data snapshot disabled, not adding scene to module (or anything else)."); + //m_log.Debug("[DATASNAPSHOT]: Data snapshot disabled, not adding scene to module (or anything else)."); } } From 5459a90fc6b3864b90a10cd99e4e5a3a0e92d226 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 16 Apr 2010 21:23:01 +0100 Subject: [PATCH 21/35] minor: stop irc bridge warning about not attached to regions if it's not been turned on in the first place --- OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs index e664b445f5..d49a4899ca 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs @@ -109,7 +109,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat } else { - m_log.WarnFormat("[IRC-Bridge] Not enabled. Connect for region {0} ignored", scene.RegionInfo.RegionName); + //m_log.DebugFormat("[IRC-Bridge] Not enabled. Connect for region {0} ignored", scene.RegionInfo.RegionName); } } From cf4673585616e4b45f095ec5837c2554f40b85b3 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 16 Apr 2010 21:39:27 +0100 Subject: [PATCH 22/35] add a missing initialization of the m_memoryCache in XmlRpcGroupsServicesConnectorModule the lack of this caused me a NullReferenceException when calling some groups methods directly though in principle it would also fail in other situations --- .../Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index e7967d1b49..79b9a167d0 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -142,8 +142,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_log.InfoFormat("[XMLRPC-GROUPS-CONNECTOR]: Groups Cache Timeout set to {0}.", m_cacheTimeout); } - // If we got all the config options we need, lets start'er'up + m_memoryCache = new ExpiringCache(); m_connectorEnabled = true; } } From bf3956aeb0a44d0dd455e330234fcf0e18f5ea43 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 16 Apr 2010 22:29:11 +0100 Subject: [PATCH 23/35] Add --skip-assets option to load oar. This allows you to load an oar without loading its assets. This is useful if you know that the required assets are already in the asset service, since loading without assets is quicker. This option will become more useful when the ability to save oars without assets is added, which should happen fairly soon. At this point there will also be better documentation. --- OpenSim/Region/Application/OpenSim.cs | 5 ++- .../World/Archiver/ArchiveReadRequest.cs | 40 ++++++++++++------- .../World/Archiver/ArchiverModule.cs | 19 +++++---- .../World/Archiver/Tests/ArchiverTests.cs | 2 +- .../Interfaces/IRegionArchiverModule.cs | 12 +++++- 5 files changed, 50 insertions(+), 28 deletions(-) mode change 100755 => 100644 OpenSim/Region/Application/OpenSim.cs diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs old mode 100755 new mode 100644 index 38b20843e0..139503074f --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -251,8 +251,9 @@ namespace OpenSim "Save named prim to XML2", SavePrimsXml2); m_console.Commands.AddCommand("region", false, "load oar", - "load oar [--merge] ", - "Load a region's data from OAR archive", LoadOar); + "load oar [--merge] [--skip-assets] ", + "Load a region's data from OAR archive. --merge will merge the oar with the existing scene. --skip-assets will load the oar but ignore the assets it contains", + LoadOar); m_console.Commands.AddCommand("region", false, "save oar", "save oar ", diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index b1b2336f83..cde7c9380d 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -53,25 +53,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding(); - private static UTF8Encoding m_utf8Encoding = new UTF8Encoding(); + protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding(); + protected static UTF8Encoding m_utf8Encoding = new UTF8Encoding(); - private Scene m_scene; - private Stream m_loadStream; - private Guid m_requestId; - private string m_errorMessage; + protected Scene m_scene; + protected Stream m_loadStream; + protected Guid m_requestId; + protected string m_errorMessage; /// /// Should the archive being loaded be merged with what is already on the region? /// - private bool m_merge; + protected bool m_merge; + + /// + /// Should we ignore any assets when reloading the archive? + /// + protected bool m_skipAssets; /// /// Used to cache lookups for valid uuids. /// private IDictionary m_validUserUuids = new Dictionary(); - public ArchiveReadRequest(Scene scene, string loadPath, bool merge, Guid requestId) + public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) { m_scene = scene; @@ -89,14 +94,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_errorMessage = String.Empty; m_merge = merge; + m_skipAssets = skipAssets; m_requestId = requestId; } - public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, Guid requestId) + public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) { m_scene = scene; m_loadStream = loadStream; m_merge = merge; + m_skipAssets = skipAssets; m_requestId = requestId; } @@ -135,7 +142,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver { serialisedSceneObjects.Add(m_utf8Encoding.GetString(data)); } - else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) + else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets) { if (LoadAsset(filePath, data)) successfulAssetRestores++; @@ -178,12 +185,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver archive.Close(); } - m_log.InfoFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores); - - if (failedAssetRestores > 0) + if (!m_skipAssets) { - m_log.ErrorFormat("[ARCHIVER]: Failed to load {0} assets", failedAssetRestores); - m_errorMessage += String.Format("Failed to load {0} assets", failedAssetRestores); + m_log.InfoFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores); + + if (failedAssetRestores > 0) + { + m_log.ErrorFormat("[ARCHIVER]: Failed to load {0} assets", failedAssetRestores); + m_errorMessage += String.Format("Failed to load {0} assets", failedAssetRestores); + } } if (!m_merge) diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index fc8d4e1d04..82ede01d01 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs @@ -94,8 +94,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver public void HandleLoadOarConsoleCommand(string module, string[] cmdparams) { bool mergeOar = false; + bool skipAssets = false; OptionSet options = new OptionSet().Add("m|merge", delegate (string v) { mergeOar = v != null; }); + options.Add("s|skip-assets", delegate (string v) { skipAssets = v != null; }); + List mainParams = options.Parse(cmdparams); // m_log.DebugFormat("MERGE OAR IS [{0}]", mergeOar); @@ -105,11 +108,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (mainParams.Count > 2) { - DearchiveRegion(mainParams[2], mergeOar, Guid.Empty); + DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty); } else { - DearchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, mergeOar, Guid.Empty); + DearchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, mergeOar, skipAssets, Guid.Empty); } } @@ -154,25 +157,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver public void DearchiveRegion(string loadPath) { - DearchiveRegion(loadPath, false, Guid.Empty); + DearchiveRegion(loadPath, false, false, Guid.Empty); } - public void DearchiveRegion(string loadPath, bool merge, Guid requestId) + public void DearchiveRegion(string loadPath, bool merge, bool skipAssets, Guid requestId) { m_log.InfoFormat( "[ARCHIVER]: Loading archive to region {0} from {1}", m_scene.RegionInfo.RegionName, loadPath); - new ArchiveReadRequest(m_scene, loadPath, merge, requestId).DearchiveRegion(); + new ArchiveReadRequest(m_scene, loadPath, merge, skipAssets, requestId).DearchiveRegion(); } public void DearchiveRegion(Stream loadStream) { - DearchiveRegion(loadStream, false, Guid.Empty); + DearchiveRegion(loadStream, false, false, Guid.Empty); } - public void DearchiveRegion(Stream loadStream, bool merge, Guid requestId) + public void DearchiveRegion(Stream loadStream, bool merge, bool skipAssets, Guid requestId) { - new ArchiveReadRequest(m_scene, loadStream, merge, requestId).DearchiveRegion(); + new ArchiveReadRequest(m_scene, loadStream, merge, skipAssets, requestId).DearchiveRegion(); } } } diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index de16d89687..624dc22044 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -442,7 +442,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests byte[] archive = archiveWriteStream.ToArray(); MemoryStream archiveReadStream = new MemoryStream(archive); - m_archiverModule.DearchiveRegion(archiveReadStream, true, Guid.Empty); + m_archiverModule.DearchiveRegion(archiveReadStream, true, false, Guid.Empty); SceneObjectPart object1Existing = m_scene.GetSceneObjectPart(part1.Name); Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge"); diff --git a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs index 991d60ca11..89e59d0f17 100644 --- a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs @@ -90,8 +90,12 @@ namespace OpenSim.Region.Framework.Interfaces /// If true, the loaded region merges with the existing one rather than replacing it. Any terrain or region /// settings in the archive will be ignored. /// + /// + /// If true, the archive is loaded without loading any assets contained within it. This is useful if the + /// assets are already known to be present in the grid's asset service. + /// /// If supplied, this request Id is later returned in the saved event - void DearchiveRegion(string loadPath, bool merge, Guid requestId); + void DearchiveRegion(string loadPath, bool merge, bool skipAssets, Guid requestId); /// /// Dearchive a region from a stream. This replaces the existing scene. @@ -113,7 +117,11 @@ namespace OpenSim.Region.Framework.Interfaces /// If true, the loaded region merges with the existing one rather than replacing it. Any terrain or region /// settings in the archive will be ignored. /// + /// + /// If true, the archive is loaded without loading any assets contained within it. This is useful if the + /// assets are already known to be present in the grid's asset service. + /// If supplied, this request Id is later returned in the saved event - void DearchiveRegion(Stream loadStream, bool merge, Guid requestId); + void DearchiveRegion(Stream loadStream, bool merge, bool skipAssets, Guid requestId); } } From e9926d13cf72ede89686147b38425fea806caeb0 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 16 Apr 2010 22:38:42 +0100 Subject: [PATCH 24/35] minor: use the static ascii and utf8 encodings instead of instantiating our own --- .../CoreModules/World/Archiver/ArchiveReadRequest.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index cde7c9380d..55028d0284 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -53,9 +53,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding(); - protected static UTF8Encoding m_utf8Encoding = new UTF8Encoding(); - protected Scene m_scene; protected Stream m_loadStream; protected Guid m_requestId; @@ -140,7 +137,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) { - serialisedSceneObjects.Add(m_utf8Encoding.GetString(data)); + serialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); } else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets) { @@ -162,7 +159,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver } else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH)) { - serialisedParcels.Add(m_utf8Encoding.GetString(data)); + serialisedParcels.Add(Encoding.UTF8.GetString(data)); } else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) { @@ -551,7 +548,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); XmlTextReader xtr - = new XmlTextReader(m_asciiEncoding.GetString(data), XmlNodeType.Document, context); + = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; From 17d023ba5bb54f832adc8c0d4ba79b2a0e67c434 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 16 Apr 2010 22:54:25 +0100 Subject: [PATCH 25/35] refactor: crudely move the RezMultipleAttachments() method into the AttachmentsModule --- .../Avatar/Attachments/AttachmentsModule.cs | 12 ++++++++++++ .../Framework/Interfaces/IAttachmentsModule.cs | 12 ++++++++++++ OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 10 ---------- OpenSim/Region/Framework/Scenes/Scene.cs | 8 ++++---- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 23828efea5..37f790d67a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -30,6 +30,7 @@ using System.Reflection; using log4net; using Nini.Config; using OpenMetaverse; +using OpenMetaverse.Packets; using OpenSim.Framework; using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; @@ -169,6 +170,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return true; } + public void RezMultipleAttachmentsFromInventory( + IClientAPI remoteClient, + RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, + RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects) + { + foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects) + { + RezSingleAttachmentFromInventory(remoteClient, obj.ItemID, obj.AttachmentPt); + } + } + public UUID RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt) { m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing single attachment from item {0} for {1}", itemID, remoteClient.Name); diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index 0222b020c7..77e9a7ec32 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -27,6 +27,7 @@ using System; using OpenMetaverse; +using OpenMetaverse.Packets; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; @@ -81,6 +82,17 @@ namespace OpenSim.Region.Framework.Interfaces UUID RezSingleAttachmentFromInventory( IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus); + /// + /// Rez multiple attachments from a user's inventory + /// + /// + /// + /// + void RezMultipleAttachmentsFromInventory( + IClientAPI remoteClient, + RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, + RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects); + /// /// Update the user inventory to the attachment of an item /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 7c68ef4eed..4a286ac9fa 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -35,7 +35,6 @@ using OpenMetaverse; using OpenMetaverse.Packets; using log4net; using OpenSim.Framework; - using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes.Serialization; @@ -1875,15 +1874,6 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerOnAttach(localID, itemID, avatarID); } - public void RezMultipleAttachments(IClientAPI remoteClient, RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, - RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects) - { - foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects) - { - AttachmentsModule.RezSingleAttachmentFromInventory(remoteClient, obj.ItemID, obj.AttachmentPt); - } - } - public void DetachSingleAttachmentToGround(UUID itemID, IClientAPI remoteClient) { SceneObjectPart part = GetSceneObjectPart(itemID); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 685a678023..d4da2cbcf6 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2769,13 +2769,13 @@ namespace OpenSim.Region.Framework.Scenes } public virtual void SubscribeToClientAttachmentEvents(IClientAPI client) - { - client.OnRezMultipleAttachmentsFromInv += RezMultipleAttachments; + { client.OnObjectDetach += m_sceneGraph.DetachObject; if (AttachmentsModule != null) { client.OnRezSingleAttachmentFromInv += AttachmentsModule.RezSingleAttachmentFromInventory; + client.OnRezMultipleAttachmentsFromInv += AttachmentsModule.RezMultipleAttachmentsFromInventory; client.OnObjectAttach += AttachmentsModule.AttachObject; client.OnDetachAttachmentIntoInv += AttachmentsModule.ShowDetachInUserInventory; } @@ -2926,12 +2926,12 @@ namespace OpenSim.Region.Framework.Scenes public virtual void UnSubscribeToClientAttachmentEvents(IClientAPI client) { - client.OnRezMultipleAttachmentsFromInv -= RezMultipleAttachments; client.OnObjectDetach -= m_sceneGraph.DetachObject; if (AttachmentsModule != null) { - client.OnRezSingleAttachmentFromInv -= AttachmentsModule.RezSingleAttachmentFromInventory; + client.OnRezSingleAttachmentFromInv -= AttachmentsModule.RezSingleAttachmentFromInventory; + client.OnRezMultipleAttachmentsFromInv -= AttachmentsModule.RezMultipleAttachmentsFromInventory; client.OnObjectAttach -= AttachmentsModule.AttachObject; client.OnDetachAttachmentIntoInv -= AttachmentsModule.ShowDetachInUserInventory; } From 45563e20e0167cd0349503919a96658ca119d11e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 16 Apr 2010 22:57:44 +0100 Subject: [PATCH 26/35] minor: correctly print out missing item id when it can't be found rather than a NullReferenceException --- .../Inventory/LocalInventoryServiceConnector.cs | 5 ++++- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs index e97d21fa1b..a2f26d5a2c 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs @@ -311,10 +311,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory { // m_log.DebugFormat("[LOCAL INVENTORY SERVICES CONNECTOR]: Requesting inventory item {0}", item.ID); + UUID requestedItemId = item.ID; + item = m_InventoryService.GetItem(item); if (null == item) - m_log.ErrorFormat("[LOCAL INVENTORY SERVICES CONNECTOR]: Could not find item with id {0}", item.ID); + m_log.ErrorFormat( + "[LOCAL INVENTORY SERVICES CONNECTOR]: Could not find item with id {0}", requestedItemId); return item; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 4a286ac9fa..a90c4b3402 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -471,7 +471,6 @@ namespace OpenSim.Region.Framework.Scenes return null; } - if (recipientParentFolderId == UUID.Zero) { InventoryFolderBase recipientRootFolder = InventoryService.GetRootFolder(recipientId); From b3e9dd4fc26d772ba61a0751347caf1daf2dd39f Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 16 Apr 2010 15:10:57 -0700 Subject: [PATCH 27/35] Bug fix in SQLite/SQLiteUserAccountData.cs: Missing'(' in one of the SQL statements. --- OpenSim/Data/SQLite/SQLiteUserAccountData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Data/SQLite/SQLiteUserAccountData.cs b/OpenSim/Data/SQLite/SQLiteUserAccountData.cs index 50e8c238f5..67cf7165b1 100644 --- a/OpenSim/Data/SQLite/SQLiteUserAccountData.cs +++ b/OpenSim/Data/SQLite/SQLiteUserAccountData.cs @@ -66,7 +66,7 @@ namespace OpenSim.Data.SQLite if (words.Length == 1) { - cmd.CommandText = String.Format("select * from {0} where ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{2}%')", + cmd.CommandText = String.Format("select * from {0} where (ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{2}%')", m_Realm, scopeID.ToString(), words[0]); } else From 57c293d604874c8033a602d1cea6f5250769ff14 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 16 Apr 2010 23:15:13 +0100 Subject: [PATCH 28/35] refactor: crudely move DetachSingleAttachmentToGround() over to the AttachmentsModule --- .../Avatar/Attachments/AttachmentsModule.cs | 32 +++++++++++++++++++ .../Interfaces/IAttachmentsModule.cs | 7 ++++ .../Framework/Scenes/Scene.Inventory.cs | 30 ----------------- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 4 +-- 4 files changed, 40 insertions(+), 33 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 37f790d67a..f8fb7ca5fd 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -341,6 +341,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments DetachSingleAttachmentToInv(itemID, remoteClient); } + public void DetachSingleAttachmentToGround(UUID itemID, IClientAPI remoteClient) + { + SceneObjectPart part = m_scene.GetSceneObjectPart(itemID); + if (part == null || part.ParentGroup == null) + return; + + UUID inventoryID = part.ParentGroup.GetFromItemID(); + + ScenePresence presence; + if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) + { + if (!m_scene.Permissions.CanRezObject( + part.ParentGroup.Children.Count, remoteClient.AgentId, presence.AbsolutePosition)) + return; + + presence.Appearance.DetachAttachment(itemID); + + if (m_scene.AvatarFactory != null) + { + m_scene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); + } + part.ParentGroup.DetachToGround(); + + List uuids = new List(); + uuids.Add(inventoryID); + m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids); + remoteClient.SendRemoveInventoryItem(inventoryID); + } + + m_scene.EventManager.TriggerOnAttach(part.ParentGroup.LocalId, itemID, UUID.Zero); + } + // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards. // To LocalId or UUID, *THAT* is the question. How now Brown UUID?? protected void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient) diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index 77e9a7ec32..d43ce1fa0b 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -92,6 +92,13 @@ namespace OpenSim.Region.Framework.Interfaces IClientAPI remoteClient, RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects); + + /// + /// Detach the given item to the ground. + /// + /// + /// + void DetachSingleAttachmentToGround(UUID itemID, IClientAPI remoteClient); /// /// Update the user inventory to the attachment of an item diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index a90c4b3402..e3f1636e54 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1873,36 +1873,6 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerOnAttach(localID, itemID, avatarID); } - public void DetachSingleAttachmentToGround(UUID itemID, IClientAPI remoteClient) - { - SceneObjectPart part = GetSceneObjectPart(itemID); - if (part == null || part.ParentGroup == null) - return; - - UUID inventoryID = part.ParentGroup.GetFromItemID(); - - ScenePresence presence; - if (TryGetScenePresence(remoteClient.AgentId, out presence)) - { - if (!Permissions.CanRezObject(part.ParentGroup.Children.Count, remoteClient.AgentId, presence.AbsolutePosition)) - return; - - presence.Appearance.DetachAttachment(itemID); - IAvatarFactory ava = RequestModuleInterface(); - if (ava != null) - { - ava.UpdateDatabase(remoteClient.AgentId, presence.Appearance); - } - part.ParentGroup.DetachToGround(); - - List uuids = new List(); - uuids.Add(inventoryID); - InventoryService.DeleteItems(remoteClient.AgentId, uuids); - remoteClient.SendRemoveInventoryItem(inventoryID); - } - SendAttachEvent(part.ParentGroup.LocalId, itemID, UUID.Zero); - } - public void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID) { EventManager.TriggerGetScriptRunning(controllingClient, objectID, itemID); diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 23a4ee9274..89eb54d1dc 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -443,9 +443,7 @@ namespace OpenSim.Region.Framework.Scenes { SceneObjectGroup group = GetGroupByPrim(objectLocalID); if (group != null) - { - m_parentScene.DetachSingleAttachmentToGround(group.UUID, remoteClient); - } + m_parentScene.AttachmentsModule.DetachSingleAttachmentToGround(group.UUID, remoteClient); } protected internal void DetachObject(uint objectLocalID, IClientAPI remoteClient) From ab3af43d5e363a47d103f75f8ee346f476dbe15d Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 16 Apr 2010 23:29:36 +0100 Subject: [PATCH 29/35] refactor: remove now unused internal method SendAttachEvent() --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index e3f1636e54..7661068605 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1868,11 +1868,6 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerStopScript(part.LocalId, itemID); } - internal void SendAttachEvent(uint localID, UUID itemID, UUID avatarID) - { - EventManager.TriggerOnAttach(localID, itemID, avatarID); - } - public void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID) { EventManager.TriggerGetScriptRunning(controllingClient, objectID, itemID); From 26e38842372e934937be36a21d8a99742cd485fe Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 17 Apr 2010 00:00:45 +0100 Subject: [PATCH 30/35] refactor: move DeatchObject() into the AttachmentsModule --- .../Avatar/Attachments/AttachmentsModule.cs | 10 ++++++++++ .../Region/Framework/Interfaces/IAttachmentsModule.cs | 10 ++++++++++ OpenSim/Region/Framework/Scenes/Scene.cs | 10 ++++------ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index f8fb7ca5fd..c87a383ee0 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -323,6 +323,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } } + public void DetachObject(uint objectLocalID, IClientAPI remoteClient) + { + SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); + if (group != null) + { + //group.DetachToGround(); + ShowDetachInUserInventory(group.GetFromItemID(), remoteClient); + } + } + public void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient) { ScenePresence presence; diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index d43ce1fa0b..f8af36756c 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -93,6 +93,16 @@ namespace OpenSim.Region.Framework.Interfaces RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects); + /// + /// Detach an object from the avatar. + /// + /// + /// This method is called in response to a client's detach request, so we only update the information in + /// inventory + /// + /// + void DetachObject(uint objectLocalID, IClientAPI remoteClient); + /// /// Detach the given item to the ground. /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index d4da2cbcf6..a34f57e7a8 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2769,14 +2769,13 @@ namespace OpenSim.Region.Framework.Scenes } public virtual void SubscribeToClientAttachmentEvents(IClientAPI client) - { - client.OnObjectDetach += m_sceneGraph.DetachObject; - + { if (AttachmentsModule != null) { client.OnRezSingleAttachmentFromInv += AttachmentsModule.RezSingleAttachmentFromInventory; client.OnRezMultipleAttachmentsFromInv += AttachmentsModule.RezMultipleAttachmentsFromInventory; client.OnObjectAttach += AttachmentsModule.AttachObject; + client.OnObjectDetach += AttachmentsModule.DetachObject; client.OnDetachAttachmentIntoInv += AttachmentsModule.ShowDetachInUserInventory; } } @@ -2925,14 +2924,13 @@ namespace OpenSim.Region.Framework.Scenes } public virtual void UnSubscribeToClientAttachmentEvents(IClientAPI client) - { - client.OnObjectDetach -= m_sceneGraph.DetachObject; - + { if (AttachmentsModule != null) { client.OnRezSingleAttachmentFromInv -= AttachmentsModule.RezSingleAttachmentFromInventory; client.OnRezMultipleAttachmentsFromInv -= AttachmentsModule.RezMultipleAttachmentsFromInventory; client.OnObjectAttach -= AttachmentsModule.AttachObject; + client.OnObjectDetach -= AttachmentsModule.DetachObject; client.OnDetachAttachmentIntoInv -= AttachmentsModule.ShowDetachInUserInventory; } } From 930d3745256ced37afb2d91817eba941d06a50b0 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 16 Apr 2010 16:36:44 -0700 Subject: [PATCH 31/35] Expose Delete at IUserAccountData interface. It was there already. No changes in IUserAccountService, just the data layer. --- OpenSim/Data/IUserAccountData.cs | 1 + OpenSim/Data/Null/NullUserAccountData.cs | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/OpenSim/Data/IUserAccountData.cs b/OpenSim/Data/IUserAccountData.cs index 6ee5995fd1..906ba6c561 100644 --- a/OpenSim/Data/IUserAccountData.cs +++ b/OpenSim/Data/IUserAccountData.cs @@ -48,6 +48,7 @@ namespace OpenSim.Data { UserAccountData[] Get(string[] fields, string[] values); bool Store(UserAccountData data); + bool Delete(string field, string val); UserAccountData[] GetUsers(UUID scopeID, string query); } } diff --git a/OpenSim/Data/Null/NullUserAccountData.cs b/OpenSim/Data/Null/NullUserAccountData.cs index fc2c5d5de2..9eb94e643c 100644 --- a/OpenSim/Data/Null/NullUserAccountData.cs +++ b/OpenSim/Data/Null/NullUserAccountData.cs @@ -135,5 +135,26 @@ namespace OpenSim.Data.Null return result; } + public bool Delete(string field, string val) + { + // Only delete by PrincipalID + if (field.Equals("PrincipalID")) + { + UUID uuid = UUID.Zero; + if (UUID.TryParse(val, out uuid) && m_DataByUUID.ContainsKey(uuid)) + { + UserAccountData account = m_DataByUUID[uuid]; + m_DataByUUID.Remove(uuid); + if (m_DataByName.ContainsKey(account.FirstName + " " + account.LastName)) + m_DataByName.Remove(account.FirstName + " " + account.LastName); + if (account.Data.ContainsKey("Email") && account.Data["Email"] != string.Empty && m_DataByEmail.ContainsKey(account.Data["Email"])) + m_DataByEmail.Remove(account.Data["Email"]); + + return true; + } + } + + return false; + } } } From 2597a3406c10de6898f1a66e469c3656aa294f43 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 16 Apr 2010 17:43:15 -0700 Subject: [PATCH 32/35] Bug fix: UserAccounts in SQLite was missing the primary key constraint. --- OpenSim/Data/SQLite/Resources/001_UserAccount.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Data/SQLite/Resources/001_UserAccount.sql b/OpenSim/Data/SQLite/Resources/001_UserAccount.sql index f9bf24c908..c38d9a762f 100644 --- a/OpenSim/Data/SQLite/Resources/001_UserAccount.sql +++ b/OpenSim/Data/SQLite/Resources/001_UserAccount.sql @@ -2,7 +2,7 @@ -- useraccounts table CREATE TABLE UserAccounts ( - PrincipalID CHAR(36) NOT NULL, + PrincipalID CHAR(36) primary key, ScopeID CHAR(36) NOT NULL, FirstName VARCHAR(64) NOT NULL, LastName VARCHAR(64) NOT NULL, From 4e1cbd1bf3f2a7d4e3dd8861e196820f35cddec9 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 16 Apr 2010 18:04:20 -0700 Subject: [PATCH 33/35] One more bug fix in sqlite sql statements. --- OpenSim/Data/SQLite/SQLiteAuthenticationData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs b/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs index 2c28375485..aa10734d50 100644 --- a/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs +++ b/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs @@ -235,7 +235,7 @@ namespace OpenSim.Data.SQLite if (System.Environment.TickCount - m_LastExpire > 30000) DoExpire(); - SqliteCommand cmd = new SqliteCommand("update tokens set validity = datetime('now, 'localtime', '+" + lifetime.ToString() + + SqliteCommand cmd = new SqliteCommand("update tokens set validity = datetime('now', 'localtime', '+" + lifetime.ToString() + " minutes') where UUID = '" + principalID.ToString() + "' and token = '" + token + "' and validity > datetime('now', 'localtime')"); if (ExecuteNonQuery(cmd, m_Connection) > 0) From 7ef6dc2bac4f25368d969f487799c2bc49c33c36 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sun, 18 Apr 2010 19:19:50 +0100 Subject: [PATCH 34/35] Slightly tweak README to account for the fact that first-time standalone users may effectively set up their avatar as 'master avatar' in the region configuration stage. --- README.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.txt b/README.txt index ed59bf56b7..f1a71beadf 100644 --- a/README.txt +++ b/README.txt @@ -59,7 +59,8 @@ Once you are presented with a prompt that looks like: You have successfully started OpenSim. -Before you can log in you will need to create a user account. You can do +Before you can log in you will need to create a user account if you didn't already create +your user as the "Master Avatar" during the region configuration stage. You can do this by running the "create user" command on the OpenSim console. This will ask you a series of questions such as first name, last name and password. From 21cad5d3ac68ceb4ac48346835ac087ecb107446 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 19 Apr 2010 06:29:26 +0100 Subject: [PATCH 35/35] All scripts are now created suspended and are only unsuspended when the object is fully rezzed and all scripts in it are instantiated. This ensures that link messages will not be lost on rez/region crossing and makes heavily scripted objects reliable. --- .../Avatar/Attachments/AttachmentsModule.cs | 3 ++- .../InventoryAccess/InventoryAccessModule.cs | 1 + .../World/Archiver/ArchiveReadRequest.cs | 1 + .../Framework/Interfaces/IEntityInventory.cs | 1 + .../Framework/Interfaces/IScriptModule.cs | 8 ++++++ .../Framework/Scenes/Scene.Inventory.cs | 2 ++ OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 1 + .../Scenes/SceneObjectGroup.Inventory.cs | 8 ++++++ .../Scenes/SceneObjectPartInventory.cs | 25 ++++++++++++++++++- .../Scenes/Serialization/SceneXmlLoader.cs | 1 + .../Interfaces/IScriptInstance.cs | 3 +++ .../Shared/Instance/ScriptInstance.cs | 14 +++++++++++ .../Region/ScriptEngine/XEngine/XEngine.cs | 18 +++++++++++++ 14 files changed, 85 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index c87a383ee0..77e73fb03c 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -250,6 +250,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments itemID, remoteClient.Name, AttachmentPt); } + objatt.ResumeScripts(); return objatt; } @@ -413,4 +414,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 16e05b7e1c..32a0df9833 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -621,6 +621,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } } + rootPart.ParentGroup.ResumeScripts(); return rootPart.ParentGroup; } } diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 55028d0284..c52f029c39 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -284,6 +284,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver { sceneObjectsLoadedCount++; sceneObject.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0); + sceneObject.ResumeScripts(); } } diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index f58904f8c8..2b90960936 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -74,6 +74,7 @@ namespace OpenSim.Region.Framework.Interfaces void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource); ArrayList GetScriptErrors(UUID itemID); + void ResumeScripts(); /// /// Stop all the scripts in this entity. diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs index e90b3004fe..fecdd1b9b8 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs @@ -41,6 +41,14 @@ namespace OpenSim.Region.Framework.Interfaces bool PostScriptEvent(UUID itemID, string name, Object[] args); bool PostObjectEvent(UUID itemID, string name, Object[] args); + // Suspend ALL scripts in a given scene object. The item ID + // is the UUID of a SOG, and the method acts on all contained + // scripts. This is different from the suspend/resume that + // can be issued by a client. + // + void SuspendScript(UUID itemID); + void ResumeScript(UUID itemID); + ArrayList GetScriptErrors(UUID itemID); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 7661068605..435026c8a5 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -63,6 +63,7 @@ namespace OpenSim.Region.Framework.Scenes if (group is SceneObjectGroup) { ((SceneObjectGroup) group).CreateScriptInstances(0, false, DefaultScriptEngine, 0); + ((SceneObjectGroup) group).ResumeScripts(); } } } @@ -218,6 +219,7 @@ namespace OpenSim.Region.Framework.Scenes { remoteClient.SendAgentAlertMessage("Script saved", false); } + part.ParentGroup.ResumeScripts(); return errors; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index a34f57e7a8..57587bedd4 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1131,7 +1131,6 @@ namespace OpenSim.Region.Framework.Scenes { if (m_scripts_enabled != !ScriptEngine) { - // Tedd! Here's the method to disable the scripting engine! if (ScriptEngine) { m_log.Info("Stopping all Scripts in Scene"); @@ -1153,6 +1152,7 @@ namespace OpenSim.Region.Framework.Scenes if (ent is SceneObjectGroup) { ((SceneObjectGroup)ent).CreateScriptInstances(0, false, DefaultScriptEngine, 0); + ((SceneObjectGroup)ent).ResumeScripts(); } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 89eb54d1dc..1421d0e974 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1755,6 +1755,7 @@ namespace OpenSim.Region.Framework.Scenes copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 0); copy.HasGroupChanged = true; copy.ScheduleGroupForFullUpdate(); + copy.ResumeScripts(); // required for physics to update it's position copy.AbsolutePosition = copy.AbsolutePosition; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index 4034744c58..f7e46afa6b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -416,5 +416,13 @@ namespace OpenSim.Region.Framework.Scenes scriptModule.SetXMLState(itemID, n.OuterXml); } } + + public void ResumeScripts() + { + foreach (SceneObjectPart part in m_parts.Values) + { + part.Inventory.ResumeScripts(); + } + } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 2e13f90b66..2b6be2989c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -1042,5 +1042,28 @@ namespace OpenSim.Region.Framework.Scenes return ret; } + + public void ResumeScripts() + { + IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); + if (engines == null) + return; + + + lock (m_items) + { + foreach (TaskInventoryItem item in m_items.Values) + { + if (item.InvType == (int)InventoryType.LSL) + { + foreach (IScriptModule engine in engines) + { + if (engine != null) + engine.ResumeScript(item.ItemID); + } + } + } + } + } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs index cf0f3451d2..b6677f092e 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs @@ -182,6 +182,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization foreach (SceneObjectGroup sceneObject in sceneObjects) { sceneObject.CreateScriptInstances(0, true, scene.DefaultScriptEngine, 0); + sceneObject.ResumeScripts(); } } diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs index ae148a9c5a..9f6ea35e31 100644 --- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs @@ -81,6 +81,9 @@ namespace OpenSim.Region.ScriptEngine.Interfaces void PostEvent(EventParams data); + void Suspend(); + void Resume(); + /// /// Process the next event queued for this script /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index d30d2dcacc..74f25aa526 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -95,6 +95,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance private bool m_startedFromSavedState; private UUID m_CurrentStateHash; private UUID m_RegionID; + private bool m_Suspended = true; private Dictionary, KeyValuePair> m_LineMap; @@ -638,6 +639,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance /// public object EventProcessor() { + if (m_Suspended) + return 0; + lock (m_Script) { EventParams data = null; @@ -1011,5 +1015,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance { get { return m_RegionID; } } + + public void Suspend() + { + m_Suspended = true; + } + + public void Resume() + { + m_Suspended = false; + } } } diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 98e77c0b92..54074ed4fd 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1488,5 +1488,23 @@ namespace OpenSim.Region.ScriptEngine.XEngine return new ArrayList(); } } + + public void SuspendScript(UUID itemID) + { + IScriptInstance instance = GetInstance(itemID); + if (instance == null) + return; + + instance.Suspend(); + } + + public void ResumeScript(UUID itemID) + { + IScriptInstance instance = GetInstance(itemID); + if (instance == null) + return; + + instance.Resume(); + } } }