diff options
Diffstat (limited to 'OpenSim/Region')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs | 20 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs | 145 |
2 files changed, 122 insertions, 43 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs b/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs index 87d3d1c..e0a11cc 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs | |||
@@ -25,20 +25,16 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | ||
29 | using System.Collections; | ||
30 | using System.Reflection; | ||
31 | using log4net; | ||
32 | using Nini.Config; | ||
33 | using Mono.Addins; | 28 | using Mono.Addins; |
29 | using Nini.Config; | ||
34 | using OpenMetaverse; | 30 | using OpenMetaverse; |
35 | using OpenSim.Framework; | 31 | using OpenSim.Capabilities.Handlers; |
36 | using OpenSim.Framework.Servers.HttpServer; | 32 | using OpenSim.Framework.Servers.HttpServer; |
37 | using OpenSim.Region.Framework.Interfaces; | 33 | using OpenSim.Region.Framework.Interfaces; |
38 | using OpenSim.Region.Framework.Scenes; | 34 | using OpenSim.Region.Framework.Scenes; |
39 | using OpenSim.Services.Interfaces; | 35 | using OpenSim.Services.Interfaces; |
36 | using System; | ||
40 | using Caps = OpenSim.Framework.Capabilities.Caps; | 37 | using Caps = OpenSim.Framework.Capabilities.Caps; |
41 | using OpenSim.Capabilities.Handlers; | ||
42 | 38 | ||
43 | namespace OpenSim.Region.ClientStack.Linden | 39 | namespace OpenSim.Region.ClientStack.Linden |
44 | { | 40 | { |
@@ -58,8 +54,6 @@ namespace OpenSim.Region.ClientStack.Linden | |||
58 | 54 | ||
59 | private string m_fetchInventory2Url; | 55 | private string m_fetchInventory2Url; |
60 | 56 | ||
61 | private FetchInventory2Handler m_fetchHandler; | ||
62 | |||
63 | #region ISharedRegionModule Members | 57 | #region ISharedRegionModule Members |
64 | 58 | ||
65 | public void Initialise(IConfigSource source) | 59 | public void Initialise(IConfigSource source) |
@@ -98,10 +92,6 @@ namespace OpenSim.Region.ClientStack.Linden | |||
98 | 92 | ||
99 | m_inventoryService = m_scene.InventoryService; | 93 | m_inventoryService = m_scene.InventoryService; |
100 | 94 | ||
101 | // We'll reuse the same handler for all requests. | ||
102 | if (m_fetchInventory2Url == "localhost") | ||
103 | m_fetchHandler = new FetchInventory2Handler(m_inventoryService); | ||
104 | |||
105 | m_scene.EventManager.OnRegisterCaps += RegisterCaps; | 95 | m_scene.EventManager.OnRegisterCaps += RegisterCaps; |
106 | } | 96 | } |
107 | 97 | ||
@@ -131,9 +121,11 @@ namespace OpenSim.Region.ClientStack.Linden | |||
131 | { | 121 | { |
132 | capUrl = "/CAPS/" + UUID.Random(); | 122 | capUrl = "/CAPS/" + UUID.Random(); |
133 | 123 | ||
124 | FetchInventory2Handler fetchHandler = new FetchInventory2Handler(m_inventoryService, agentID); | ||
125 | |||
134 | IRequestHandler reqHandler | 126 | IRequestHandler reqHandler |
135 | = new RestStreamHandler( | 127 | = new RestStreamHandler( |
136 | "POST", capUrl, m_fetchHandler.FetchInventoryRequest, capName, agentID.ToString()); | 128 | "POST", capUrl, fetchHandler.FetchInventoryRequest, capName, agentID.ToString()); |
137 | 129 | ||
138 | caps.RegisterHandler(capName, reqHandler); | 130 | caps.RegisterHandler(capName, reqHandler); |
139 | } | 131 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs index 5f3e66a..2a252e1 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs | |||
@@ -66,7 +66,26 @@ namespace OpenSim.Region.ClientStack.Linden | |||
66 | 66 | ||
67 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 67 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
68 | 68 | ||
69 | private Scene m_scene; | 69 | /// <summary> |
70 | /// Control whether requests will be processed asynchronously. | ||
71 | /// </summary> | ||
72 | /// <remarks> | ||
73 | /// Defaults to true. Can currently not be changed once a region has been added to the module. | ||
74 | /// </remarks> | ||
75 | public bool ProcessQueuedRequestsAsync { get; private set; } | ||
76 | |||
77 | /// <summary> | ||
78 | /// Number of inventory requests processed by this module. | ||
79 | /// </summary> | ||
80 | /// <remarks> | ||
81 | /// It's the PollServiceRequestManager that actually sends completed requests back to the requester. | ||
82 | /// </remarks> | ||
83 | public static int ProcessedRequestsCount { get; set; } | ||
84 | |||
85 | private static Stat s_queuedRequestsStat; | ||
86 | private static Stat s_processedRequestsStat; | ||
87 | |||
88 | public Scene Scene { get; private set; } | ||
70 | 89 | ||
71 | private IInventoryService m_InventoryService; | 90 | private IInventoryService m_InventoryService; |
72 | private ILibraryService m_LibraryService; | 91 | private ILibraryService m_LibraryService; |
@@ -76,7 +95,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
76 | private string m_fetchInventoryDescendents2Url; | 95 | private string m_fetchInventoryDescendents2Url; |
77 | private string m_webFetchInventoryDescendentsUrl; | 96 | private string m_webFetchInventoryDescendentsUrl; |
78 | 97 | ||
79 | private static WebFetchInvDescHandler m_webFetchHandler; | 98 | private static FetchInvDescHandler m_webFetchHandler; |
80 | 99 | ||
81 | private static Thread[] m_workerThreads = null; | 100 | private static Thread[] m_workerThreads = null; |
82 | 101 | ||
@@ -85,6 +104,13 @@ namespace OpenSim.Region.ClientStack.Linden | |||
85 | 104 | ||
86 | #region ISharedRegionModule Members | 105 | #region ISharedRegionModule Members |
87 | 106 | ||
107 | public WebFetchInvDescModule() : this(true) {} | ||
108 | |||
109 | public WebFetchInvDescModule(bool processQueuedResultsAsync) | ||
110 | { | ||
111 | ProcessQueuedRequestsAsync = processQueuedResultsAsync; | ||
112 | } | ||
113 | |||
88 | public void Initialise(IConfigSource source) | 114 | public void Initialise(IConfigSource source) |
89 | { | 115 | { |
90 | IConfig config = source.Configs["ClientStack.LindenCaps"]; | 116 | IConfig config = source.Configs["ClientStack.LindenCaps"]; |
@@ -92,8 +118,9 @@ namespace OpenSim.Region.ClientStack.Linden | |||
92 | return; | 118 | return; |
93 | 119 | ||
94 | m_fetchInventoryDescendents2Url = config.GetString("Cap_FetchInventoryDescendents2", string.Empty); | 120 | m_fetchInventoryDescendents2Url = config.GetString("Cap_FetchInventoryDescendents2", string.Empty); |
95 | m_webFetchInventoryDescendentsUrl = config.GetString("Cap_WebFetchInventoryDescendents", string.Empty); | 121 | // m_webFetchInventoryDescendentsUrl = config.GetString("Cap_WebFetchInventoryDescendents", string.Empty); |
96 | 122 | ||
123 | // if (m_fetchInventoryDescendents2Url != string.Empty || m_webFetchInventoryDescendentsUrl != string.Empty) | ||
97 | if (m_fetchInventoryDescendents2Url != string.Empty || m_webFetchInventoryDescendentsUrl != string.Empty) | 124 | if (m_fetchInventoryDescendents2Url != string.Empty || m_webFetchInventoryDescendentsUrl != string.Empty) |
98 | { | 125 | { |
99 | m_Enabled = true; | 126 | m_Enabled = true; |
@@ -105,7 +132,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
105 | if (!m_Enabled) | 132 | if (!m_Enabled) |
106 | return; | 133 | return; |
107 | 134 | ||
108 | m_scene = s; | 135 | Scene = s; |
109 | } | 136 | } |
110 | 137 | ||
111 | public void RemoveRegion(Scene s) | 138 | public void RemoveRegion(Scene s) |
@@ -113,12 +140,23 @@ namespace OpenSim.Region.ClientStack.Linden | |||
113 | if (!m_Enabled) | 140 | if (!m_Enabled) |
114 | return; | 141 | return; |
115 | 142 | ||
116 | m_scene.EventManager.OnRegisterCaps -= RegisterCaps; | 143 | Scene.EventManager.OnRegisterCaps -= RegisterCaps; |
117 | 144 | ||
118 | foreach (Thread t in m_workerThreads) | 145 | StatsManager.DeregisterStat(s_processedRequestsStat); |
119 | Watchdog.AbortThread(t.ManagedThreadId); | 146 | StatsManager.DeregisterStat(s_queuedRequestsStat); |
147 | |||
148 | if (ProcessQueuedRequestsAsync) | ||
149 | { | ||
150 | if (m_workerThreads != null) | ||
151 | { | ||
152 | foreach (Thread t in m_workerThreads) | ||
153 | Watchdog.AbortThread(t.ManagedThreadId); | ||
120 | 154 | ||
121 | m_scene = null; | 155 | m_workerThreads = null; |
156 | } | ||
157 | } | ||
158 | |||
159 | Scene = null; | ||
122 | } | 160 | } |
123 | 161 | ||
124 | public void RegionLoaded(Scene s) | 162 | public void RegionLoaded(Scene s) |
@@ -126,19 +164,51 @@ namespace OpenSim.Region.ClientStack.Linden | |||
126 | if (!m_Enabled) | 164 | if (!m_Enabled) |
127 | return; | 165 | return; |
128 | 166 | ||
129 | m_InventoryService = m_scene.InventoryService; | 167 | if (s_processedRequestsStat == null) |
130 | m_LibraryService = m_scene.LibraryService; | 168 | s_processedRequestsStat = |
169 | new Stat( | ||
170 | "ProcessedFetchInventoryRequests", | ||
171 | "Number of processed fetch inventory requests", | ||
172 | "These have not necessarily yet been dispatched back to the requester.", | ||
173 | "", | ||
174 | "inventory", | ||
175 | "httpfetch", | ||
176 | StatType.Pull, | ||
177 | MeasuresOfInterest.AverageChangeOverTime, | ||
178 | stat => { stat.Value = ProcessedRequestsCount; }, | ||
179 | StatVerbosity.Debug); | ||
180 | |||
181 | if (s_queuedRequestsStat == null) | ||
182 | s_queuedRequestsStat = | ||
183 | new Stat( | ||
184 | "QueuedFetchInventoryRequests", | ||
185 | "Number of fetch inventory requests queued for processing", | ||
186 | "", | ||
187 | "", | ||
188 | "inventory", | ||
189 | "httpfetch", | ||
190 | StatType.Pull, | ||
191 | MeasuresOfInterest.AverageChangeOverTime, | ||
192 | stat => { stat.Value = m_queue.Count; }, | ||
193 | StatVerbosity.Debug); | ||
194 | |||
195 | StatsManager.RegisterStat(s_processedRequestsStat); | ||
196 | StatsManager.RegisterStat(s_queuedRequestsStat); | ||
197 | |||
198 | m_InventoryService = Scene.InventoryService; | ||
199 | m_LibraryService = Scene.LibraryService; | ||
131 | 200 | ||
132 | // We'll reuse the same handler for all requests. | 201 | // We'll reuse the same handler for all requests. |
133 | m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService); | 202 | m_webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService, Scene); |
134 | 203 | ||
135 | m_scene.EventManager.OnRegisterCaps += RegisterCaps; | 204 | Scene.EventManager.OnRegisterCaps += RegisterCaps; |
136 | 205 | ||
137 | if (m_workerThreads == null) | 206 | int nworkers = 2; // was 2 |
207 | if (ProcessQueuedRequestsAsync && m_workerThreads == null) | ||
138 | { | 208 | { |
139 | m_workerThreads = new Thread[2]; | 209 | m_workerThreads = new Thread[nworkers]; |
140 | 210 | ||
141 | for (uint i = 0; i < 2; i++) | 211 | for (uint i = 0; i < nworkers; i++) |
142 | { | 212 | { |
143 | m_workerThreads[i] = WorkManager.StartThread(DoInventoryRequests, | 213 | m_workerThreads[i] = WorkManager.StartThread(DoInventoryRequests, |
144 | String.Format("InventoryWorkerThread{0}", i), | 214 | String.Format("InventoryWorkerThread{0}", i), |
@@ -173,12 +243,12 @@ namespace OpenSim.Region.ClientStack.Linden | |||
173 | private Dictionary<UUID, Hashtable> responses = | 243 | private Dictionary<UUID, Hashtable> responses = |
174 | new Dictionary<UUID, Hashtable>(); | 244 | new Dictionary<UUID, Hashtable>(); |
175 | 245 | ||
176 | private Scene m_scene; | 246 | private WebFetchInvDescModule m_module; |
177 | 247 | ||
178 | public PollServiceInventoryEventArgs(Scene scene, string url, UUID pId) : | 248 | public PollServiceInventoryEventArgs(WebFetchInvDescModule module, string url, UUID pId) : |
179 | base(null, url, null, null, null, pId, int.MaxValue) | 249 | base(null, url, null, null, null, pId, int.MaxValue) |
180 | { | 250 | { |
181 | m_scene = scene; | 251 | m_module = module; |
182 | 252 | ||
183 | HasEvents = (x, y) => { lock (responses) return responses.ContainsKey(x); }; | 253 | HasEvents = (x, y) => { lock (responses) return responses.ContainsKey(x); }; |
184 | GetEvents = (x, y) => | 254 | GetEvents = (x, y) => |
@@ -198,12 +268,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
198 | 268 | ||
199 | Request = (x, y) => | 269 | Request = (x, y) => |
200 | { | 270 | { |
201 | ScenePresence sp = m_scene.GetScenePresence(Id); | 271 | ScenePresence sp = m_module.Scene.GetScenePresence(Id); |
202 | if (sp == null) | ||
203 | { | ||
204 | m_log.ErrorFormat("[INVENTORY]: Unable to find ScenePresence for {0}", Id); | ||
205 | return; | ||
206 | } | ||
207 | 272 | ||
208 | aPollRequest reqinfo = new aPollRequest(); | 273 | aPollRequest reqinfo = new aPollRequest(); |
209 | reqinfo.thepoll = this; | 274 | reqinfo.thepoll = this; |
@@ -298,7 +363,13 @@ namespace OpenSim.Region.ClientStack.Linden | |||
298 | requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null); | 363 | requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null); |
299 | 364 | ||
300 | lock (responses) | 365 | lock (responses) |
366 | { | ||
367 | if (responses.ContainsKey(requestID)) | ||
368 | m_log.WarnFormat("[FETCH INVENTORY DESCENDENTS2 MODULE]: Caught in the act of loosing responses! Please report this on mantis #7054"); | ||
301 | responses[requestID] = response; | 369 | responses[requestID] = response; |
370 | } | ||
371 | |||
372 | WebFetchInvDescModule.ProcessedRequestsCount++; | ||
302 | } | 373 | } |
303 | } | 374 | } |
304 | 375 | ||
@@ -322,7 +393,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
322 | capUrl = "/CAPS/" + UUID.Random() + "/"; | 393 | capUrl = "/CAPS/" + UUID.Random() + "/"; |
323 | 394 | ||
324 | // Register this as a poll service | 395 | // Register this as a poll service |
325 | PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(m_scene, capUrl, agentID); | 396 | PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(this, capUrl, agentID); |
326 | args.Type = PollServiceEventArgs.EventType.Inventory; | 397 | args.Type = PollServiceEventArgs.EventType.Inventory; |
327 | 398 | ||
328 | caps.RegisterPollHandler(capName, args); | 399 | caps.RegisterPollHandler(capName, args); |
@@ -331,7 +402,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
331 | else | 402 | else |
332 | { | 403 | { |
333 | capUrl = url; | 404 | capUrl = url; |
334 | IExternalCapsModule handler = m_scene.RequestModuleInterface<IExternalCapsModule>(); | 405 | IExternalCapsModule handler = Scene.RequestModuleInterface<IExternalCapsModule>(); |
335 | if (handler != null) | 406 | if (handler != null) |
336 | handler.RegisterExternalUserCapsHandler(agentID,caps,capName,capUrl); | 407 | handler.RegisterExternalUserCapsHandler(agentID,caps,capName,capUrl); |
337 | else | 408 | else |
@@ -360,10 +431,26 @@ namespace OpenSim.Region.ClientStack.Linden | |||
360 | { | 431 | { |
361 | Watchdog.UpdateThread(); | 432 | Watchdog.UpdateThread(); |
362 | 433 | ||
363 | aPollRequest poolreq = m_queue.Dequeue(); | 434 | WaitProcessQueuedInventoryRequest(); |
435 | } | ||
436 | } | ||
437 | |||
438 | public void WaitProcessQueuedInventoryRequest() | ||
439 | { | ||
440 | aPollRequest poolreq = m_queue.Dequeue(); | ||
364 | 441 | ||
365 | if (poolreq != null && poolreq.thepoll != null) | 442 | if (poolreq != null && poolreq.thepoll != null) |
443 | { | ||
444 | try | ||
445 | { | ||
366 | poolreq.thepoll.Process(poolreq); | 446 | poolreq.thepoll.Process(poolreq); |
447 | } | ||
448 | catch (Exception e) | ||
449 | { | ||
450 | m_log.ErrorFormat( | ||
451 | "[INVENTORY]: Failed to process queued inventory request {0} for {1} in {2}. Exception {3}", | ||
452 | poolreq.reqID, poolreq.presence != null ? poolreq.presence.Name : "unknown", Scene.Name, e); | ||
453 | } | ||
367 | } | 454 | } |
368 | } | 455 | } |
369 | } | 456 | } |