diff options
author | Adam Frisby | 2008-07-06 02:27:10 +0000 |
---|---|---|
committer | Adam Frisby | 2008-07-06 02:27:10 +0000 |
commit | 55dda821805a9fb94996c46594a03ba719d8f32b (patch) | |
tree | 38862f567a08d7a45f8fbd2456165fcbce5ef2fb /OpenSim/Region | |
parent | alters a problem path cut angle for the cylinder prim profile (diff) | |
download | opensim-SC-55dda821805a9fb94996c46594a03ba719d8f32b.zip opensim-SC-55dda821805a9fb94996c46594a03ba719d8f32b.tar.gz opensim-SC-55dda821805a9fb94996c46594a03ba719d8f32b.tar.bz2 opensim-SC-55dda821805a9fb94996c46594a03ba719d8f32b.tar.xz |
* Moves sending items to inventory via a delete into a seperate thread (this thread can be expanded to support all sends to inventory from inworld easily enough). Thread is temporary and only exists while items are being returned.
* This should remove the "lag" caused by deleting many objects.
* Patch brought to you by Joshua Nightshade's bitching at me to fix it.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Environment/Scenes/Scene.Inventory.cs | 264 |
1 files changed, 172 insertions, 92 deletions
diff --git a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs index 513d40d..36ca51b 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs | |||
@@ -29,6 +29,7 @@ using System; | |||
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Reflection; | 30 | using System.Reflection; |
31 | using System.Text; | 31 | using System.Text; |
32 | using System.Timers; | ||
32 | using libsecondlife; | 33 | using libsecondlife; |
33 | using libsecondlife.Packets; | 34 | using libsecondlife.Packets; |
34 | using log4net; | 35 | using log4net; |
@@ -38,8 +39,20 @@ using OpenSim.Region.Environment.Interfaces; | |||
38 | 39 | ||
39 | namespace OpenSim.Region.Environment.Scenes | 40 | namespace OpenSim.Region.Environment.Scenes |
40 | { | 41 | { |
42 | class DeleteToInventoryHolder | ||
43 | { | ||
44 | public DeRezObjectPacket DeRezPacket; | ||
45 | public EntityBase selectedEnt; | ||
46 | public IClientAPI remoteClient; | ||
47 | public SceneObjectGroup objectGroup; | ||
48 | public LLUUID folderID; | ||
49 | } | ||
50 | |||
41 | public partial class Scene | 51 | public partial class Scene |
42 | { | 52 | { |
53 | private Timer m_inventoryTicker; | ||
54 | private readonly Queue<DeleteToInventoryHolder> m_inventoryDeletes = new Queue<DeleteToInventoryHolder>(); | ||
55 | |||
43 | private static readonly ILog m_log | 56 | private static readonly ILog m_log |
44 | = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 57 | = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
45 | 58 | ||
@@ -1395,7 +1408,7 @@ namespace OpenSim.Region.Environment.Scenes | |||
1395 | /// Called when an object is removed from the environment into inventory. | 1408 | /// Called when an object is removed from the environment into inventory. |
1396 | /// </summary> | 1409 | /// </summary> |
1397 | /// <param name="packet"></param> | 1410 | /// <param name="packet"></param> |
1398 | /// <param name="simClient"></param> | 1411 | /// <param name="remoteClient"></param> |
1399 | public virtual void DeRezObject(Packet packet, IClientAPI remoteClient) | 1412 | public virtual void DeRezObject(Packet packet, IClientAPI remoteClient) |
1400 | { | 1413 | { |
1401 | DeRezObjectPacket DeRezPacket = (DeRezObjectPacket) packet; | 1414 | DeRezObjectPacket DeRezPacket = (DeRezObjectPacket) packet; |
@@ -1453,12 +1466,84 @@ namespace OpenSim.Region.Environment.Scenes | |||
1453 | 1466 | ||
1454 | if (permissionToTake) | 1467 | if (permissionToTake) |
1455 | { | 1468 | { |
1456 | string sceneObjectXml = objectGroup.ToXmlString(); | 1469 | if (m_inventoryTicker != null) |
1470 | { | ||
1471 | m_inventoryTicker.Stop(); | ||
1472 | } | ||
1473 | else | ||
1474 | { | ||
1475 | m_inventoryTicker = new Timer(2000); | ||
1476 | m_inventoryTicker.AutoReset = false; | ||
1477 | m_inventoryTicker.Elapsed += InventoryRunDeleteTimer; | ||
1478 | } | ||
1457 | 1479 | ||
1458 | CachedUserInfo userInfo = | 1480 | lock(m_inventoryDeletes) |
1459 | CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); | ||
1460 | if (userInfo != null) | ||
1461 | { | 1481 | { |
1482 | DeleteToInventoryHolder dtis = new DeleteToInventoryHolder(); | ||
1483 | dtis.DeRezPacket = DeRezPacket; | ||
1484 | dtis.folderID = folderID; | ||
1485 | dtis.objectGroup = objectGroup; | ||
1486 | dtis.remoteClient = remoteClient; | ||
1487 | dtis.selectedEnt = selectedEnt; | ||
1488 | |||
1489 | m_inventoryDeletes.Enqueue(dtis); | ||
1490 | } | ||
1491 | |||
1492 | m_inventoryTicker.Start(); | ||
1493 | |||
1494 | // Visually remove it, even if it isnt really gone yet. | ||
1495 | objectGroup.FakeDeleteGroup(); | ||
1496 | } | ||
1497 | else if (permissionToDelete) | ||
1498 | { | ||
1499 | DeleteSceneObject(objectGroup); | ||
1500 | } | ||
1501 | } | ||
1502 | } | ||
1503 | } | ||
1504 | |||
1505 | void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e) | ||
1506 | { | ||
1507 | m_log.Info("Starting inventory send loop"); | ||
1508 | while (InventoryDeQueueAndDelete() == true) | ||
1509 | { | ||
1510 | m_log.Info("Returned item successfully, continuing..."); | ||
1511 | } | ||
1512 | } | ||
1513 | |||
1514 | private bool InventoryDeQueueAndDelete() | ||
1515 | { | ||
1516 | DeleteToInventoryHolder x; | ||
1517 | try | ||
1518 | { | ||
1519 | lock (m_inventoryDeletes) | ||
1520 | { | ||
1521 | int left = m_inventoryDeletes.Count; | ||
1522 | if (left > 0) | ||
1523 | { | ||
1524 | m_log.InfoFormat("Sending deleted object to user's inventory, {0} item(s) remaining.", left); | ||
1525 | x = m_inventoryDeletes.Dequeue(); | ||
1526 | DeleteToInventory(x.DeRezPacket, x.selectedEnt, x.remoteClient, x.objectGroup, x.folderID); | ||
1527 | return true; | ||
1528 | } | ||
1529 | } | ||
1530 | } catch(Exception e) | ||
1531 | { | ||
1532 | m_log.Error(e.ToString()); | ||
1533 | } | ||
1534 | |||
1535 | m_log.Info("No objects left in inventory delete queue."); | ||
1536 | return false; | ||
1537 | } | ||
1538 | |||
1539 | private void DeleteToInventory(DeRezObjectPacket DeRezPacket, EntityBase selectedEnt, IClientAPI remoteClient, SceneObjectGroup objectGroup, LLUUID folderID) | ||
1540 | { | ||
1541 | string sceneObjectXml = objectGroup.ToXmlString(); | ||
1542 | |||
1543 | CachedUserInfo userInfo = | ||
1544 | CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); | ||
1545 | if (userInfo != null) | ||
1546 | { | ||
1462 | // string searchFolder = ""; | 1547 | // string searchFolder = ""; |
1463 | 1548 | ||
1464 | // if (DeRezPacket.AgentBlock.Destination == 6) | 1549 | // if (DeRezPacket.AgentBlock.Destination == 6) |
@@ -1466,103 +1551,98 @@ namespace OpenSim.Region.Environment.Scenes | |||
1466 | // else if (DeRezPacket.AgentBlock.Destination == 9) | 1551 | // else if (DeRezPacket.AgentBlock.Destination == 9) |
1467 | // searchFolder = "Lost And Found"; | 1552 | // searchFolder = "Lost And Found"; |
1468 | 1553 | ||
1469 | // If we're deleting someone else's item, it goes back to their deleted items folder | 1554 | // If we're deleting someone else's item, it goes back to their deleted items folder |
1470 | // If we're returning someone's item, it goes back to the owner's Lost And Found folder. | 1555 | // If we're returning someone's item, it goes back to the owner's Lost And Found folder. |
1471 | 1556 | ||
1472 | if (DeRezPacket.AgentBlock.DestinationID == LLUUID.Zero || (DeRezPacket.AgentBlock.Destination == 6 && objectGroup.OwnerID != remoteClient.AgentId)) | 1557 | if (DeRezPacket.AgentBlock.DestinationID == LLUUID.Zero || (DeRezPacket.AgentBlock.Destination == 6 && objectGroup.OwnerID != remoteClient.AgentId)) |
1473 | { | 1558 | { |
1474 | List<InventoryFolderBase> subrootfolders = userInfo.RootFolder.RequestListOfFolders(); | 1559 | List<InventoryFolderBase> subrootfolders = userInfo.RootFolder.RequestListOfFolders(); |
1475 | foreach (InventoryFolderBase flder in subrootfolders) | 1560 | foreach (InventoryFolderBase flder in subrootfolders) |
1476 | { | 1561 | { |
1477 | if (flder.Name == "Lost And Found") | 1562 | if (flder.Name == "Lost And Found") |
1478 | { | 1563 | { |
1479 | folderID = flder.ID; | 1564 | folderID = flder.ID; |
1480 | break; | 1565 | break; |
1481 | } | 1566 | } |
1482 | } | 1567 | } |
1483 | 1568 | ||
1484 | if (folderID == LLUUID.Zero) | 1569 | if (folderID == LLUUID.Zero) |
1485 | { | 1570 | { |
1486 | folderID = userInfo.RootFolder.ID; | 1571 | folderID = userInfo.RootFolder.ID; |
1487 | } | 1572 | } |
1488 | //currently following code not used (or don't know of any case of destination being zero | 1573 | //currently following code not used (or don't know of any case of destination being zero |
1489 | } | 1574 | } |
1490 | else | 1575 | else |
1491 | { | 1576 | { |
1492 | folderID = DeRezPacket.AgentBlock.DestinationID; | 1577 | folderID = DeRezPacket.AgentBlock.DestinationID; |
1493 | } | 1578 | } |
1494 | 1579 | ||
1495 | AssetBase asset = CreateAsset( | 1580 | AssetBase asset = CreateAsset( |
1496 | ((SceneObjectGroup) selectedEnt).GetPartName(selectedEnt.LocalId), | 1581 | ((SceneObjectGroup) selectedEnt).GetPartName(selectedEnt.LocalId), |
1497 | ((SceneObjectGroup) selectedEnt).GetPartDescription(selectedEnt.LocalId), | 1582 | ((SceneObjectGroup) selectedEnt).GetPartDescription(selectedEnt.LocalId), |
1498 | (sbyte)AssetType.Object, | 1583 | (sbyte)AssetType.Object, |
1499 | Helpers.StringToField(sceneObjectXml)); | 1584 | Helpers.StringToField(sceneObjectXml)); |
1500 | AssetCache.AddAsset(asset); | 1585 | AssetCache.AddAsset(asset); |
1501 | |||
1502 | InventoryItemBase item = new InventoryItemBase(); | ||
1503 | item.Creator = objectGroup.RootPart.CreatorID; | ||
1504 | |||
1505 | if (DeRezPacket.AgentBlock.Destination == 1 || DeRezPacket.AgentBlock.Destination == 4)// Take / Copy | ||
1506 | item.Owner = remoteClient.AgentId; | ||
1507 | else // Delete / Return | ||
1508 | item.Owner = objectGroup.OwnerID; | ||
1509 | |||
1510 | item.ID = LLUUID.Random(); | ||
1511 | item.AssetID = asset.FullID; | ||
1512 | item.Description = asset.Description; | ||
1513 | item.Name = asset.Name; | ||
1514 | item.AssetType = asset.Type; | ||
1515 | item.InvType = (int)InventoryType.Object; | ||
1516 | item.Folder = folderID; | ||
1517 | if ((remoteClient.AgentId != objectGroup.RootPart.OwnerID) && ExternalChecks.ExternalChecksPropagatePermissions()) | ||
1518 | { | ||
1519 | uint perms=objectGroup.GetEffectivePermissions(); | ||
1520 | uint nextPerms=(perms & 7) << 13; | ||
1521 | if ((nextPerms & (uint)PermissionMask.Copy) == 0) | ||
1522 | perms &= ~(uint)PermissionMask.Copy; | ||
1523 | if ((nextPerms & (uint)PermissionMask.Transfer) == 0) | ||
1524 | perms &= ~(uint)PermissionMask.Transfer; | ||
1525 | if ((nextPerms & (uint)PermissionMask.Modify) == 0) | ||
1526 | perms &= ~(uint)PermissionMask.Modify; | ||
1527 | |||
1528 | item.BasePermissions = perms & objectGroup.RootPart.NextOwnerMask; | ||
1529 | item.CurrentPermissions = item.BasePermissions; | ||
1530 | item.NextPermissions = objectGroup.RootPart.NextOwnerMask; | ||
1531 | item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask & objectGroup.RootPart.NextOwnerMask; | ||
1532 | item.CurrentPermissions |= 8; // Slam! | ||
1533 | } | ||
1534 | else | ||
1535 | { | ||
1536 | item.BasePermissions = objectGroup.GetEffectivePermissions(); | ||
1537 | item.CurrentPermissions = objectGroup.GetEffectivePermissions(); | ||
1538 | item.NextPermissions = objectGroup.RootPart.NextOwnerMask; | ||
1539 | item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask; | ||
1540 | } | ||
1541 | 1586 | ||
1542 | // TODO: add the new fields (Flags, Sale info, etc) | 1587 | InventoryItemBase item = new InventoryItemBase(); |
1588 | item.Creator = objectGroup.RootPart.CreatorID; | ||
1543 | 1589 | ||
1544 | userInfo.AddItem(item); | 1590 | if (DeRezPacket.AgentBlock.Destination == 1 || DeRezPacket.AgentBlock.Destination == 4)// Take / Copy |
1545 | if (item.Owner == remoteClient.AgentId) | 1591 | item.Owner = remoteClient.AgentId; |
1546 | { | 1592 | else // Delete / Return |
1547 | remoteClient.SendInventoryItemCreateUpdate(item); | 1593 | item.Owner = objectGroup.OwnerID; |
1548 | } | ||
1549 | else | ||
1550 | { | ||
1551 | ScenePresence notifyUser = GetScenePresence(item.Owner); | ||
1552 | if (notifyUser != null) | ||
1553 | { | ||
1554 | notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item); | ||
1555 | } | ||
1556 | } | ||
1557 | } | ||
1558 | } | ||
1559 | 1594 | ||
1560 | if (permissionToDelete) | 1595 | item.ID = LLUUID.Random(); |
1596 | item.AssetID = asset.FullID; | ||
1597 | item.Description = asset.Description; | ||
1598 | item.Name = asset.Name; | ||
1599 | item.AssetType = asset.Type; | ||
1600 | item.InvType = (int)InventoryType.Object; | ||
1601 | item.Folder = folderID; | ||
1602 | if ((remoteClient.AgentId != objectGroup.RootPart.OwnerID) && ExternalChecks.ExternalChecksPropagatePermissions()) | ||
1603 | { | ||
1604 | uint perms=objectGroup.GetEffectivePermissions(); | ||
1605 | uint nextPerms=(perms & 7) << 13; | ||
1606 | if ((nextPerms & (uint)PermissionMask.Copy) == 0) | ||
1607 | perms &= ~(uint)PermissionMask.Copy; | ||
1608 | if ((nextPerms & (uint)PermissionMask.Transfer) == 0) | ||
1609 | perms &= ~(uint)PermissionMask.Transfer; | ||
1610 | if ((nextPerms & (uint)PermissionMask.Modify) == 0) | ||
1611 | perms &= ~(uint)PermissionMask.Modify; | ||
1612 | |||
1613 | item.BasePermissions = perms & objectGroup.RootPart.NextOwnerMask; | ||
1614 | item.CurrentPermissions = item.BasePermissions; | ||
1615 | item.NextPermissions = objectGroup.RootPart.NextOwnerMask; | ||
1616 | item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask & objectGroup.RootPart.NextOwnerMask; | ||
1617 | item.CurrentPermissions |= 8; // Slam! | ||
1618 | } | ||
1619 | else | ||
1620 | { | ||
1621 | item.BasePermissions = objectGroup.GetEffectivePermissions(); | ||
1622 | item.CurrentPermissions = objectGroup.GetEffectivePermissions(); | ||
1623 | item.NextPermissions = objectGroup.RootPart.NextOwnerMask; | ||
1624 | item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask; | ||
1625 | } | ||
1626 | |||
1627 | // TODO: add the new fields (Flags, Sale info, etc) | ||
1628 | |||
1629 | userInfo.AddItem(item); | ||
1630 | if (item.Owner == remoteClient.AgentId) | ||
1631 | { | ||
1632 | remoteClient.SendInventoryItemCreateUpdate(item); | ||
1633 | } | ||
1634 | else | ||
1635 | { | ||
1636 | ScenePresence notifyUser = GetScenePresence(item.Owner); | ||
1637 | if (notifyUser != null) | ||
1561 | { | 1638 | { |
1562 | DeleteSceneObject(objectGroup); | 1639 | notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item); |
1563 | } | 1640 | } |
1564 | } | 1641 | } |
1565 | } | 1642 | } |
1643 | |||
1644 | // Finally remove the item, for reals this time. | ||
1645 | DeleteSceneObject(objectGroup); | ||
1566 | } | 1646 | } |
1567 | 1647 | ||
1568 | public void updateKnownAsset(IClientAPI remoteClient, SceneObjectGroup grp, LLUUID assetID, LLUUID agentID) | 1648 | public void updateKnownAsset(IClientAPI remoteClient, SceneObjectGroup grp, LLUUID assetID, LLUUID agentID) |