aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs145
1 files changed, 116 insertions, 29 deletions
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 }