aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Framework/IClientAPI.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs156
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs25
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs5
5 files changed, 165 insertions, 28 deletions
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 659d42f..f6e2977 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -737,7 +737,7 @@ namespace OpenSim.Framework
737 bool IsActive { get; set; } 737 bool IsActive { get; set; }
738 738
739 /// <value> 739 /// <value>
740 /// Determines whether the client is logging out or not. 740 /// Determines whether the client is or has been removed from a given scene
741 /// </value> 741 /// </value>
742 bool IsLoggingOut { get; set; } 742 bool IsLoggingOut { get; set; }
743 743
diff --git a/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs
new file mode 100644
index 0000000..06cd14b
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs
@@ -0,0 +1,156 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Threading;
32using log4net;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36
37namespace OpenSim.Region.Framework.Scenes
38{
39 class FetchHolder
40 {
41 public IClientAPI Client { get; private set; }
42 public UUID ItemID { get; private set; }
43
44 public FetchHolder(IClientAPI client, UUID itemID)
45 {
46 Client = client;
47 ItemID = itemID;
48 }
49 }
50
51 /// <summary>
52 /// Send FetchInventoryReply information to clients asynchronously on a single thread rather than asynchronously via
53 /// multiple threads.
54 /// </summary>
55 /// <remarks>
56 /// If the main root inventory is right-clicked on a version 1 viewer for a user with a large inventory, a very
57 /// very large number of FetchInventory requests are sent to the simulator. Each is handled on a separate thread
58 /// by the IClientAPI, but the sheer number of requests overwhelms the number of threads available and ends up
59 /// freezing the inbound packet handling.
60 ///
61 /// This class makes the first FetchInventory packet thread process the queue. If new requests come
62 /// in while it is processing, then the subsequent threads just add the requests and leave it to the original
63 /// thread to process them.
64 ///
65 /// This might slow down outbound packets but these are limited by the IClientAPI outbound queues
66 /// anyway.
67 ///
68 /// It might be possible to ignore FetchInventory requests altogether, particularly as they are redundant wrt to
69 /// FetchInventoryDescendents requests, but this would require more investigation.
70 /// </remarks>
71 public class AsyncInventorySender
72 {
73 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
74
75 protected Scene m_scene;
76
77 /// <summary>
78 /// Queues fetch requests
79 /// </summary>
80 Queue<FetchHolder> m_fetchHolder = new Queue<FetchHolder>();
81
82 /// <summary>
83 /// Signal whether a queue is currently being processed or not.
84 /// </summary>
85 protected volatile bool m_processing;
86
87 public AsyncInventorySender(Scene scene)
88 {
89 m_processing = false;
90 m_scene = scene;
91 }
92
93 /// <summary>
94 /// Handle a fetch inventory request from the client
95 /// </summary>
96 /// <param name="remoteClient"></param>
97 /// <param name="itemID"></param>
98 /// <param name="ownerID"></param>
99 public void HandleFetchInventory(IClientAPI remoteClient, UUID itemID, UUID ownerID)
100 {
101 lock (m_fetchHolder)
102 {
103// m_log.DebugFormat(
104// "[ASYNC INVENTORY SENDER]: Putting request from {0} for {1} on queue", remoteClient.Name, itemID);
105
106 m_fetchHolder.Enqueue(new FetchHolder(remoteClient, itemID));
107 }
108
109 if (!m_processing)
110 {
111 m_processing = true;
112 ProcessQueue();
113 }
114 }
115
116 /// <summary>
117 /// Process the queue of fetches
118 /// </summary>
119 protected void ProcessQueue()
120 {
121 FetchHolder fh = null;
122
123 while (true)
124 {
125 lock (m_fetchHolder)
126 {
127// m_log.DebugFormat("[ASYNC INVENTORY SENDER]: {0} items left to process", m_fetchHolder.Count);
128
129 if (m_fetchHolder.Count == 0)
130 {
131 m_processing = false;
132 return;
133 }
134 else
135 {
136 fh = m_fetchHolder.Dequeue();
137 }
138 }
139
140 if (fh.Client.IsLoggingOut)
141 continue;
142
143// m_log.DebugFormat(
144// "[ASYNC INVENTORY SENDER]: Handling request from {0} for {1} on queue", fh.Client.Name, fh.ItemID);
145
146 InventoryItemBase item = new InventoryItemBase(fh.ItemID, fh.Client.AgentId);
147 item = m_scene.InventoryService.GetItem(item);
148
149 if (item != null)
150 fh.Client.SendInventoryItemDetails(item.Owner, item);
151
152 // TODO: Possibly log any failure
153 }
154 }
155 }
156} \ 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 13085e3..30421d4 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -52,6 +52,11 @@ namespace OpenSim.Region.Framework.Scenes
52 protected AsyncSceneObjectGroupDeleter m_asyncSceneObjectDeleter; 52 protected AsyncSceneObjectGroupDeleter m_asyncSceneObjectDeleter;
53 53
54 /// <summary> 54 /// <summary>
55 /// Allows inventory details to be sent to clients asynchronously
56 /// </summary>
57 protected AsyncInventorySender m_asyncInventorySender;
58
59 /// <summary>
55 /// Start all the scripts in the scene which should be started. 60 /// Start all the scripts in the scene which should be started.
56 /// </summary> 61 /// </summary>
57 public void CreateScriptInstances() 62 public void CreateScriptInstances()
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index e2d7208..44472b2 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -461,31 +461,6 @@ namespace OpenSim.Region.Framework.Scenes
461 } 461 }
462 ); 462 );
463 } 463 }
464
465
466 /// <summary>
467 /// Handle a fetch inventory request from the client
468 /// </summary>
469 /// <param name="remoteClient"></param>
470 /// <param name="itemID"></param>
471 /// <param name="ownerID"></param>
472 public void HandleFetchInventory(IClientAPI remoteClient, UUID itemID, UUID ownerID)
473 {
474 if (LibraryService != null && LibraryService.LibraryRootFolder != null && ownerID == LibraryService.LibraryRootFolder.Owner)
475 {
476 //m_log.Debug("request info for library item");
477 return;
478 }
479
480 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
481 item = InventoryService.GetItem(item);
482
483 if (item != null)
484 {
485 remoteClient.SendInventoryItemDetails(ownerID, item);
486 }
487 // else shouldn't we send an alert message?
488 }
489 464
490 /// <summary> 465 /// <summary>
491 /// Tell the client about the various child items and folders contained in the requested folder. 466 /// Tell the client about the various child items and folders contained in the requested folder.
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index ad41e88..eeb881f 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -583,6 +583,8 @@ namespace OpenSim.Region.Framework.Scenes
583 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 583 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
584 m_asyncSceneObjectDeleter.Enabled = true; 584 m_asyncSceneObjectDeleter.Enabled = true;
585 585
586 m_asyncInventorySender = new AsyncInventorySender(this);
587
586 #region Region Settings 588 #region Region Settings
587 589
588 // Load region settings 590 // Load region settings
@@ -2760,14 +2762,13 @@ namespace OpenSim.Region.Framework.Scenes
2760 2762
2761 public virtual void SubscribeToClientInventoryEvents(IClientAPI client) 2763 public virtual void SubscribeToClientInventoryEvents(IClientAPI client)
2762 { 2764 {
2763
2764 client.OnLinkInventoryItem += HandleLinkInventoryItem; 2765 client.OnLinkInventoryItem += HandleLinkInventoryItem;
2765 client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder; 2766 client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder;
2766 client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder; 2767 client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder;
2767 client.OnMoveInventoryFolder += HandleMoveInventoryFolder; // 2; //!! 2768 client.OnMoveInventoryFolder += HandleMoveInventoryFolder; // 2; //!!
2768 client.OnFetchInventoryDescendents += HandleFetchInventoryDescendents; 2769 client.OnFetchInventoryDescendents += HandleFetchInventoryDescendents;
2769 client.OnPurgeInventoryDescendents += HandlePurgeInventoryDescendents; // 2; //!! 2770 client.OnPurgeInventoryDescendents += HandlePurgeInventoryDescendents; // 2; //!!
2770 client.OnFetchInventory += HandleFetchInventory; 2771 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2771 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2772 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2772 client.OnCopyInventoryItem += CopyInventoryItem; 2773 client.OnCopyInventoryItem += CopyInventoryItem;
2773 client.OnMoveInventoryItem += MoveInventoryItem; 2774 client.OnMoveInventoryItem += MoveInventoryItem;