diff options
Diffstat (limited to 'OpenSim/Region/Framework')
6 files changed, 179 insertions, 99 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index d16b73b..51f6c5e 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -1757,6 +1757,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1757 | { | 1757 | { |
1758 | if (group != null) | 1758 | if (group != null) |
1759 | { | 1759 | { |
1760 | group.HasGroupChanged = true; | ||
1760 | group.ProcessBackup(SimulationDataService, true); | 1761 | group.ProcessBackup(SimulationDataService, true); |
1761 | } | 1762 | } |
1762 | } | 1763 | } |
@@ -2345,13 +2346,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2345 | { | 2346 | { |
2346 | if (!softDelete) | 2347 | if (!softDelete) |
2347 | { | 2348 | { |
2348 | // Force a database update so that the scene object group ID is accurate. It's possible that the | 2349 | // If the group contains prims whose SceneGroupID is incorrect then force a |
2349 | // group has recently been delinked from another group but that this change has not been persisted | 2350 | // database update, because RemoveObject() works by searching on the SceneGroupID. |
2350 | // to the DB. | ||
2351 | // This is an expensive thing to do so only do it if absolutely necessary. | 2351 | // This is an expensive thing to do so only do it if absolutely necessary. |
2352 | if (so.HasGroupChangedDueToDelink) | 2352 | if (so.GroupContainsForeignPrims) |
2353 | ForceSceneObjectBackup(so); | 2353 | ForceSceneObjectBackup(so); |
2354 | 2354 | ||
2355 | so.DetachFromBackup(); | 2355 | so.DetachFromBackup(); |
2356 | SimulationDataService.RemoveObject(so.UUID, RegionInfo.RegionID); | 2356 | SimulationDataService.RemoveObject(so.UUID, RegionInfo.RegionID); |
2357 | } | 2357 | } |
@@ -3413,6 +3413,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3413 | // TeleportFlags.ViaLandmark | TeleportFlags.ViaLocation | TeleportFlags.ViaLandmark | TeleportFlags.Default - Regular Teleport | 3413 | // TeleportFlags.ViaLandmark | TeleportFlags.ViaLocation | TeleportFlags.ViaLandmark | TeleportFlags.Default - Regular Teleport |
3414 | 3414 | ||
3415 | // Don't disable this log message - it's too helpful | 3415 | // Don't disable this log message - it's too helpful |
3416 | string curViewer = Util.GetViewerName(acd); | ||
3416 | m_log.DebugFormat( | 3417 | m_log.DebugFormat( |
3417 | "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})", | 3418 | "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})", |
3418 | RegionInfo.RegionName, | 3419 | RegionInfo.RegionName, |
@@ -3422,7 +3423,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3422 | acd.AgentID, | 3423 | acd.AgentID, |
3423 | acd.circuitcode, | 3424 | acd.circuitcode, |
3424 | acd.IPAddress, | 3425 | acd.IPAddress, |
3425 | acd.Viewer, | 3426 | curViewer, |
3426 | ((TPFlags)teleportFlags).ToString(), | 3427 | ((TPFlags)teleportFlags).ToString(), |
3427 | acd.startpos | 3428 | acd.startpos |
3428 | ); | 3429 | ); |
@@ -3442,7 +3443,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3442 | { | 3443 | { |
3443 | foreach (string viewer in m_AllowedViewers) | 3444 | foreach (string viewer in m_AllowedViewers) |
3444 | { | 3445 | { |
3445 | if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower()) | 3446 | if (viewer == curViewer.Substring(0, viewer.Length).Trim().ToLower()) |
3446 | { | 3447 | { |
3447 | ViewerDenied = false; | 3448 | ViewerDenied = false; |
3448 | break; | 3449 | break; |
@@ -3459,7 +3460,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3459 | { | 3460 | { |
3460 | foreach (string viewer in m_BannedViewers) | 3461 | foreach (string viewer in m_BannedViewers) |
3461 | { | 3462 | { |
3462 | if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower()) | 3463 | if (viewer == curViewer.Substring(0, viewer.Length).Trim().ToLower()) |
3463 | { | 3464 | { |
3464 | ViewerDenied = true; | 3465 | ViewerDenied = true; |
3465 | break; | 3466 | break; |
@@ -3471,7 +3472,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3471 | { | 3472 | { |
3472 | m_log.DebugFormat( | 3473 | m_log.DebugFormat( |
3473 | "[SCENE]: Access denied for {0} {1} using {2}", | 3474 | "[SCENE]: Access denied for {0} {1} using {2}", |
3474 | acd.firstname, acd.lastname, acd.Viewer); | 3475 | acd.firstname, acd.lastname, curViewer); |
3475 | reason = "Access denied, your viewer is banned by the region owner"; | 3476 | reason = "Access denied, your viewer is banned by the region owner"; |
3476 | return false; | 3477 | return false; |
3477 | } | 3478 | } |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 6f26176..b70e9df 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -150,12 +150,27 @@ namespace OpenSim.Region.Framework.Scenes | |||
150 | 150 | ||
151 | get { return m_hasGroupChanged; } | 151 | get { return m_hasGroupChanged; } |
152 | } | 152 | } |
153 | |||
154 | private bool m_groupContainsForeignPrims = false; | ||
153 | 155 | ||
154 | /// <summary> | 156 | /// <summary> |
155 | /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since | 157 | /// Whether the group contains prims that came from a different group. This happens when |
156 | /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation. | 158 | /// linking or delinking groups. The implication is that until the group is persisted, |
159 | /// the prims in the database still use the old SceneGroupID. That's a problem if the group | ||
160 | /// is deleted, because we delete groups by searching for prims by their SceneGroupID. | ||
157 | /// </summary> | 161 | /// </summary> |
158 | public bool HasGroupChangedDueToDelink { get; private set; } | 162 | public bool GroupContainsForeignPrims |
163 | { | ||
164 | private set | ||
165 | { | ||
166 | m_groupContainsForeignPrims = value; | ||
167 | if (m_groupContainsForeignPrims) | ||
168 | HasGroupChanged = true; | ||
169 | } | ||
170 | |||
171 | get { return m_groupContainsForeignPrims; } | ||
172 | } | ||
173 | |||
159 | 174 | ||
160 | private bool isTimeToPersist() | 175 | private bool isTimeToPersist() |
161 | { | 176 | { |
@@ -1624,7 +1639,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1624 | backup_group.RootPart.AngularVelocity = RootPart.AngularVelocity; | 1639 | backup_group.RootPart.AngularVelocity = RootPart.AngularVelocity; |
1625 | backup_group.RootPart.ParticleSystem = RootPart.ParticleSystem; | 1640 | backup_group.RootPart.ParticleSystem = RootPart.ParticleSystem; |
1626 | HasGroupChanged = false; | 1641 | HasGroupChanged = false; |
1627 | HasGroupChangedDueToDelink = false; | 1642 | GroupContainsForeignPrims = false; |
1628 | 1643 | ||
1629 | m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); | 1644 | m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); |
1630 | datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); | 1645 | datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); |
@@ -1686,28 +1701,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1686 | SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); | 1701 | SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); |
1687 | dupe.Backup = false; | 1702 | dupe.Backup = false; |
1688 | dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); | 1703 | dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); |
1689 | |||
1690 | // Warning, The following code related to previousAttachmentStatus is needed so that clones of | ||
1691 | // attachments do not bordercross while they're being duplicated. This is hacktastic! | ||
1692 | // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! | ||
1693 | // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state | ||
1694 | // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, | ||
1695 | // then restore it's attachment state | ||
1696 | |||
1697 | // This is only necessary when userExposed is false! | ||
1698 | |||
1699 | bool previousAttachmentStatus = dupe.IsAttachment; | ||
1700 | |||
1701 | if (!userExposed) | ||
1702 | dupe.IsAttachment = true; | ||
1703 | |||
1704 | dupe.m_sittingAvatars = new List<UUID>(); | 1704 | dupe.m_sittingAvatars = new List<UUID>(); |
1705 | |||
1706 | if (!userExposed) | ||
1707 | { | ||
1708 | dupe.IsAttachment = previousAttachmentStatus; | ||
1709 | } | ||
1710 | |||
1711 | dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); | 1705 | dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); |
1712 | dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; | 1706 | dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; |
1713 | 1707 | ||
@@ -2388,6 +2382,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2388 | // If linking prims with different permissions, fix them | 2382 | // If linking prims with different permissions, fix them |
2389 | AdjustChildPrimPermissions(); | 2383 | AdjustChildPrimPermissions(); |
2390 | 2384 | ||
2385 | GroupContainsForeignPrims = true; | ||
2386 | |||
2391 | AttachToBackup(); | 2387 | AttachToBackup(); |
2392 | 2388 | ||
2393 | // Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the | 2389 | // Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the |
@@ -2531,9 +2527,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
2531 | 2527 | ||
2532 | linkPart.Rezzed = RootPart.Rezzed; | 2528 | linkPart.Rezzed = RootPart.Rezzed; |
2533 | 2529 | ||
2534 | // When we delete a group, we currently have to force persist to the database if the object id has changed | 2530 | // We must persist the delinked group to the database immediately, for safety. The problem |
2535 | // (since delete works by deleting all rows which have a given object id) | 2531 | // is that although in memory the new group has a new SceneGroupID, in the database it |
2536 | objectGroup.HasGroupChangedDueToDelink = true; | 2532 | // still has the parent group's SceneGroupID (until the next backup). This means that if the |
2533 | // parent group is deleted then the delinked group will also be deleted from the database. | ||
2534 | // This problem will disappear if the region remains alive long enough for another backup, | ||
2535 | // since at that time the delinked group's new SceneGroupID will be written to the database. | ||
2536 | // But if the region crashes before that then the prims will be permanently gone, and this must | ||
2537 | // not happen. (We can't use a just-in-time trick like GroupContainsForeignPrims in this case | ||
2538 | // because the delinked group doesn't know when the source group is deleted.) | ||
2539 | m_scene.ForceSceneObjectBackup(objectGroup); | ||
2537 | 2540 | ||
2538 | return objectGroup; | 2541 | return objectGroup; |
2539 | } | 2542 | } |
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 491d0bf..64c464d 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -848,7 +848,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
848 | 848 | ||
849 | public string Viewer | 849 | public string Viewer |
850 | { | 850 | { |
851 | get { return m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode).Viewer; } | 851 | get { return Util.GetViewerName(m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode)); } |
852 | } | 852 | } |
853 | 853 | ||
854 | #endregion | 854 | #endregion |
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs index 5cb271d..a556f9d 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs | |||
@@ -119,21 +119,22 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
119 | return output; | 119 | return output; |
120 | } | 120 | } |
121 | } | 121 | } |
122 | 122 | ||
123 | public static bool TryFromXml(string xml, out CoalescedSceneObjects coa) | 123 | public static bool TryFromXml(string xml, out CoalescedSceneObjects coa) |
124 | { | 124 | { |
125 | // m_log.DebugFormat("[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() deserializing {0}", xml); | 125 | // m_log.DebugFormat("[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() deserializing {0}", xml); |
126 | 126 | ||
127 | coa = null; | 127 | coa = null; |
128 | int i = 0; | ||
129 | 128 | ||
130 | using (StringReader sr = new StringReader(xml)) | 129 | try |
131 | { | 130 | { |
132 | using (XmlTextReader reader = new XmlTextReader(sr)) | 131 | // Quickly check if this is a coalesced object, without fully parsing the XML |
133 | { | 132 | using (StringReader sr = new StringReader(xml)) |
134 | try | 133 | { |
134 | using (XmlTextReader reader = new XmlTextReader(sr)) | ||
135 | { | 135 | { |
136 | reader.Read(); | 136 | reader.MoveToContent(); // skip possible xml declaration |
137 | |||
137 | if (reader.Name != "CoalescedObject") | 138 | if (reader.Name != "CoalescedObject") |
138 | { | 139 | { |
139 | // m_log.DebugFormat( | 140 | // m_log.DebugFormat( |
@@ -142,49 +143,49 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
142 | 143 | ||
143 | return false; | 144 | return false; |
144 | } | 145 | } |
145 | 146 | } | |
146 | coa = new CoalescedSceneObjects(UUID.Zero); | 147 | } |
147 | reader.Read(); | ||
148 | |||
149 | while (reader.NodeType != XmlNodeType.EndElement && reader.Name != "CoalescedObject") | ||
150 | { | ||
151 | if (reader.Name == "SceneObjectGroup") | ||
152 | { | ||
153 | string soXml = reader.ReadOuterXml(); | ||
154 | |||
155 | SceneObjectGroup so = SceneObjectSerializer.FromOriginalXmlFormat(soXml); | ||
156 | |||
157 | if (so != null) | ||
158 | { | ||
159 | coa.Add(so); | ||
160 | } | ||
161 | else | ||
162 | { | ||
163 | // XXX: Possibly we should fail outright here rather than continuing if a particular component of the | ||
164 | // coalesced object fails to load. | ||
165 | m_log.WarnFormat( | ||
166 | "[COALESCED SCENE OBJECTS SERIALIZER]: Deserialization of xml for component {0} failed. Continuing.", | ||
167 | i); | ||
168 | } | ||
169 | 148 | ||
170 | i++; | 149 | XmlDocument doc = new XmlDocument(); |
171 | } | 150 | doc.LoadXml(xml); |
172 | } | 151 | XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject"); |
152 | if (e == null) | ||
153 | return false; | ||
173 | 154 | ||
174 | reader.ReadEndElement(); // CoalescedObject | 155 | coa = new CoalescedSceneObjects(UUID.Zero); |
156 | |||
157 | XmlNodeList groups = e.SelectNodes("SceneObjectGroup"); | ||
158 | int i = 0; | ||
159 | |||
160 | foreach (XmlNode n in groups) | ||
161 | { | ||
162 | SceneObjectGroup so = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml); | ||
163 | if (so != null) | ||
164 | { | ||
165 | coa.Add(so); | ||
175 | } | 166 | } |
176 | catch (Exception e) | 167 | else |
177 | { | 168 | { |
178 | m_log.ErrorFormat( | 169 | // XXX: Possibly we should fail outright here rather than continuing if a particular component of the |
179 | "[COALESCED SCENE OBJECTS SERIALIZER]: Deserialization of xml failed with {0} {1}", | 170 | // coalesced object fails to load. |
180 | e.Message, e.StackTrace); | 171 | m_log.WarnFormat( |
181 | 172 | "[COALESCED SCENE OBJECTS SERIALIZER]: Deserialization of xml for component {0} failed. Continuing.", | |
182 | return false; | 173 | i); |
183 | } | 174 | } |
175 | |||
176 | i++; | ||
184 | } | 177 | } |
185 | } | 178 | } |
179 | catch (Exception e) | ||
180 | { | ||
181 | m_log.Error(string.Format( | ||
182 | "[COALESCED SCENE OBJECTS SERIALIZER]: Deserialization of xml failed with {0} ", | ||
183 | e.Message), e); | ||
184 | |||
185 | return false; | ||
186 | } | ||
186 | 187 | ||
187 | return true; | 188 | return true; |
188 | } | 189 | } |
189 | } | 190 | } |
190 | } \ No newline at end of file | 191 | } |
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index f07dee9..a93f3c8 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs | |||
@@ -299,6 +299,73 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
299 | } | 299 | } |
300 | } | 300 | } |
301 | 301 | ||
302 | |||
303 | /// <summary> | ||
304 | /// Modifies a SceneObjectGroup. | ||
305 | /// </summary> | ||
306 | /// <param name="sog">The object</param> | ||
307 | /// <returns>Whether the object was actually modified</returns> | ||
308 | public delegate bool SceneObjectModifier(SceneObjectGroup sog); | ||
309 | |||
310 | /// <summary> | ||
311 | /// Modifies an object by deserializing it; applying 'modifier' to each SceneObjectGroup; and reserializing. | ||
312 | /// </summary> | ||
313 | /// <param name="assetId">The object's UUID</param> | ||
314 | /// <param name="data">Serialized data</param> | ||
315 | /// <param name="modifier">The function to run on each SceneObjectGroup</param> | ||
316 | /// <returns>The new serialized object's data, or null if an error occurred</returns> | ||
317 | public static byte[] ModifySerializedObject(UUID assetId, byte[] data, SceneObjectModifier modifier) | ||
318 | { | ||
319 | List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); | ||
320 | CoalescedSceneObjects coa = null; | ||
321 | |||
322 | string xmlData = Utils.BytesToString(data); | ||
323 | |||
324 | if (CoalescedSceneObjectsSerializer.TryFromXml(xmlData, out coa)) | ||
325 | { | ||
326 | // m_log.DebugFormat("[SERIALIZER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count); | ||
327 | |||
328 | if (coa.Objects.Count == 0) | ||
329 | { | ||
330 | m_log.WarnFormat("[SERIALIZER]: Aborting load of coalesced object from asset {0} as it has zero loaded components", assetId); | ||
331 | return null; | ||
332 | } | ||
333 | |||
334 | sceneObjects.AddRange(coa.Objects); | ||
335 | } | ||
336 | else | ||
337 | { | ||
338 | SceneObjectGroup deserializedObject = FromOriginalXmlFormat(xmlData); | ||
339 | |||
340 | if (deserializedObject != null) | ||
341 | { | ||
342 | sceneObjects.Add(deserializedObject); | ||
343 | } | ||
344 | else | ||
345 | { | ||
346 | m_log.WarnFormat("[SERIALIZER]: Aborting load of object from asset {0} as deserialization failed", assetId); | ||
347 | return null; | ||
348 | } | ||
349 | } | ||
350 | |||
351 | bool modified = false; | ||
352 | foreach (SceneObjectGroup sog in sceneObjects) | ||
353 | { | ||
354 | if (modifier(sog)) | ||
355 | modified = true; | ||
356 | } | ||
357 | |||
358 | if (modified) | ||
359 | { | ||
360 | if (coa != null) | ||
361 | data = Utils.StringToBytes(CoalescedSceneObjectsSerializer.ToXml(coa)); | ||
362 | else | ||
363 | data = Utils.StringToBytes(ToOriginalXmlFormat(sceneObjects[0])); | ||
364 | } | ||
365 | |||
366 | return data; | ||
367 | } | ||
368 | |||
302 | 369 | ||
303 | #region manual serialization | 370 | #region manual serialization |
304 | 371 | ||
@@ -1230,7 +1297,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1230 | if (m_UserManagement == null) | 1297 | if (m_UserManagement == null) |
1231 | m_UserManagement = sop.ParentGroup.Scene.RequestModuleInterface<IUserManagement>(); | 1298 | m_UserManagement = sop.ParentGroup.Scene.RequestModuleInterface<IUserManagement>(); |
1232 | string name = m_UserManagement.GetUserName(sop.CreatorID); | 1299 | string name = m_UserManagement.GetUserName(sop.CreatorID); |
1233 | writer.WriteElementString("CreatorData", (string)options["home"] + ";" + name); | 1300 | writer.WriteElementString("CreatorData", ExternalRepresentationUtils.CalcCreatorData((string)options["home"], name)); |
1234 | } | 1301 | } |
1235 | 1302 | ||
1236 | WriteUUID(writer, "FolderID", sop.FolderID, options); | 1303 | WriteUUID(writer, "FolderID", sop.FolderID, options); |
@@ -1403,7 +1470,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1403 | if (m_UserManagement == null) | 1470 | if (m_UserManagement == null) |
1404 | m_UserManagement = scene.RequestModuleInterface<IUserManagement>(); | 1471 | m_UserManagement = scene.RequestModuleInterface<IUserManagement>(); |
1405 | string name = m_UserManagement.GetUserName(item.CreatorID); | 1472 | string name = m_UserManagement.GetUserName(item.CreatorID); |
1406 | writer.WriteElementString("CreatorData", (string)options["home"] + ";" + name); | 1473 | writer.WriteElementString("CreatorData", ExternalRepresentationUtils.CalcCreatorData((string)options["home"], name)); |
1407 | } | 1474 | } |
1408 | 1475 | ||
1409 | writer.WriteElementString("Description", item.Description); | 1476 | writer.WriteElementString("Description", item.Description); |
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs index 9378e20..c928b1e 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs | |||
@@ -91,7 +91,12 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
91 | grp2.RootPart.ClearUpdateSchedule(); | 91 | grp2.RootPart.ClearUpdateSchedule(); |
92 | 92 | ||
93 | // Link grp2 to grp1. part2 becomes child prim to grp1. grp2 is eliminated. | 93 | // Link grp2 to grp1. part2 becomes child prim to grp1. grp2 is eliminated. |
94 | Assert.IsFalse(grp1.GroupContainsForeignPrims); | ||
94 | grp1.LinkToGroup(grp2); | 95 | grp1.LinkToGroup(grp2); |
96 | Assert.IsTrue(grp1.GroupContainsForeignPrims); | ||
97 | |||
98 | scene.Backup(true); | ||
99 | Assert.IsFalse(grp1.GroupContainsForeignPrims); | ||
95 | 100 | ||
96 | // FIXME: Can't do this test yet since group 2 still has its root part! We can't yet null this since | 101 | // FIXME: Can't do this test yet since group 2 still has its root part! We can't yet null this since |
97 | // it might cause SOG.ProcessBackup() to fail due to the race condition. This really needs to be fixed. | 102 | // it might cause SOG.ProcessBackup() to fail due to the race condition. This really needs to be fixed. |
@@ -143,7 +148,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
143 | 148 | ||
144 | Assert.That(grp1.Parts.Length, Is.EqualTo(1), "Group 1 still contained part2 after delink."); | 149 | Assert.That(grp1.Parts.Length, Is.EqualTo(1), "Group 1 still contained part2 after delink."); |
145 | Assert.That(part2.AbsolutePosition == Vector3.Zero, "The absolute position should be zero"); | 150 | Assert.That(part2.AbsolutePosition == Vector3.Zero, "The absolute position should be zero"); |
146 | Assert.That(grp3.HasGroupChangedDueToDelink, Is.True); | ||
147 | } | 151 | } |
148 | 152 | ||
149 | [Test] | 153 | [Test] |
@@ -335,30 +339,34 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
335 | SceneObjectPart rootPart | 339 | SceneObjectPart rootPart |
336 | = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) | 340 | = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) |
337 | { Name = rootPartName, UUID = rootPartUuid }; | 341 | { Name = rootPartName, UUID = rootPartUuid }; |
342 | |||
338 | SceneObjectPart linkPart | 343 | SceneObjectPart linkPart |
339 | = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) | 344 | = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) |
340 | { Name = linkPartName, UUID = linkPartUuid }; | 345 | { Name = linkPartName, UUID = linkPartUuid }; |
346 | SceneObjectGroup linkGroup = new SceneObjectGroup(linkPart); | ||
347 | scene.AddNewSceneObject(linkGroup, true); | ||
341 | 348 | ||
342 | SceneObjectGroup sog = new SceneObjectGroup(rootPart); | 349 | SceneObjectGroup sog = new SceneObjectGroup(rootPart); |
343 | sog.AddPart(linkPart); | 350 | scene.AddNewSceneObject(sog, true); |
344 | scene.AddNewSceneObject(sog, true); | 351 | |
345 | 352 | Assert.IsFalse(sog.GroupContainsForeignPrims); | |
346 | // In a test, we have to crank the backup handle manually. Normally this would be done by the timer invoked | 353 | sog.LinkToGroup(linkGroup); |
347 | // scene backup thread. | 354 | Assert.IsTrue(sog.GroupContainsForeignPrims); |
355 | |||
348 | scene.Backup(true); | 356 | scene.Backup(true); |
349 | 357 | Assert.AreEqual(1, scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID).Count); | |
358 | |||
350 | // These changes should occur immediately without waiting for a backup pass | 359 | // These changes should occur immediately without waiting for a backup pass |
351 | SceneObjectGroup groupToDelete = sog.DelinkFromGroup(linkPart, false); | 360 | SceneObjectGroup groupToDelete = sog.DelinkFromGroup(linkPart, false); |
352 | 361 | Assert.IsFalse(groupToDelete.GroupContainsForeignPrims); | |
353 | Assert.That(groupToDelete.HasGroupChangedDueToDelink, Is.True); | 362 | |
354 | scene.DeleteSceneObject(groupToDelete, false); | 363 | scene.DeleteSceneObject(groupToDelete, false); |
355 | Assert.That(groupToDelete.HasGroupChangedDueToDelink, Is.False); | ||
356 | 364 | ||
357 | List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID); | 365 | List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID); |
358 | 366 | ||
359 | Assert.That(storedObjects.Count, Is.EqualTo(1)); | 367 | Assert.AreEqual(1, storedObjects.Count); |
360 | Assert.That(storedObjects[0].Parts.Length, Is.EqualTo(1)); | 368 | Assert.AreEqual(1, storedObjects[0].Parts.Length); |
361 | Assert.That(storedObjects[0].ContainsPart(rootPartUuid)); | 369 | Assert.IsTrue(storedObjects[0].ContainsPart(rootPartUuid)); |
362 | } | 370 | } |
363 | } | 371 | } |
364 | } | 372 | } |