aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorMelanie2012-09-11 10:39:43 +0200
committerMelanie2012-09-11 10:39:43 +0200
commita6753c14a509e11f65829b87070b440ac3b87c4a (patch)
tree3ead3fb646684c12149e0ccdffd98e44632e6db6 /OpenSim
parentRemove commented code (diff)
downloadopensim-SC-a6753c14a509e11f65829b87070b440ac3b87c4a.zip
opensim-SC-a6753c14a509e11f65829b87070b440ac3b87c4a.tar.gz
opensim-SC-a6753c14a509e11f65829b87070b440ac3b87c4a.tar.bz2
opensim-SC-a6753c14a509e11f65829b87070b440ac3b87c4a.tar.xz
Revamp the v3 inventory sending. Uses threads and some nifty mechanics to
leverage the Poll Service without blocking it's workers.
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs198
1 files changed, 117 insertions, 81 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index e996fe8..4908c2c 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -42,6 +42,7 @@ using OpenSim.Region.Framework.Scenes;
42using OpenSim.Services.Interfaces; 42using OpenSim.Services.Interfaces;
43using Caps = OpenSim.Framework.Capabilities.Caps; 43using Caps = OpenSim.Framework.Capabilities.Caps;
44using OpenSim.Capabilities.Handlers; 44using OpenSim.Capabilities.Handlers;
45using OpenSim.Framework.Monitoring;
45 46
46namespace OpenSim.Region.ClientStack.Linden 47namespace OpenSim.Region.ClientStack.Linden
47{ 48{
@@ -58,13 +59,13 @@ namespace OpenSim.Region.ClientStack.Linden
58 private IInventoryService m_InventoryService; 59 private IInventoryService m_InventoryService;
59 private ILibraryService m_LibraryService; 60 private ILibraryService m_LibraryService;
60 61
61 private WebFetchInvDescHandler m_webFetchHandler; 62 private static WebFetchInvDescHandler m_webFetchHandler;
62
63 private object m_lock = new object();
64 63
65 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>(); 64 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
66 private Dictionary<UUID, Hashtable> m_requests = new Dictionary<UUID, Hashtable>(); 65 private static Thread[] m_workerThreads = null;
67 bool m_busy = false; 66
67 private static OpenMetaverse.BlockingQueue<PollServiceInventoryEventArgs> m_queue =
68 new OpenMetaverse.BlockingQueue<PollServiceInventoryEventArgs>();
68 69
69 #region ISharedRegionModule Members 70 #region ISharedRegionModule Members
70 71
@@ -94,6 +95,22 @@ namespace OpenSim.Region.ClientStack.Linden
94 95
95 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 96 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
96 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps; 97 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
98
99 if (m_workerThreads == null)
100 {
101 m_workerThreads = new Thread[2];
102
103 for (uint i = 0; i < 2; i++)
104 {
105 m_workerThreads[i] = Watchdog.StartThread(DoInventoryRequests,
106 String.Format("InventoryWorkerThread{0}", i),
107 ThreadPriority.Normal,
108 false,
109 true,
110 null,
111 int.MaxValue);
112 }
113 }
97 } 114 }
98 115
99 public void PostInitialise() 116 public void PostInitialise()
@@ -111,13 +128,103 @@ namespace OpenSim.Region.ClientStack.Linden
111 128
112 #endregion 129 #endregion
113 130
131 ~WebFetchInvDescModule()
132 {
133 foreach (Thread t in m_workerThreads)
134 t.Abort();
135 }
136
137 private class PollServiceInventoryEventArgs : PollServiceEventArgs
138 {
139 private List<Hashtable> requests =
140 new List<Hashtable>();
141 private Dictionary<UUID, Hashtable> responses =
142 new Dictionary<UUID, Hashtable>();
143
144 public PollServiceInventoryEventArgs(UUID pId) :
145 base(null, null, null, null, pId, 30000)
146 {
147 HasEvents = (x, y) => { return this.responses.ContainsKey(x); };
148 GetEvents = (x, y, s) =>
149 {
150 try
151 {
152 return this.responses[x];
153 }
154 finally
155 {
156 responses.Remove(x);
157 }
158 };
159
160 Request = (x, y) =>
161 {
162 y["RequestID"] = x.ToString();
163 lock (this.requests)
164 this.requests.Add(y);
165
166 m_queue.Enqueue(this);
167 };
168
169 NoEvents = (x, y) =>
170 {
171 lock (this.requests)
172 {
173 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
174 requests.Remove(request);
175 }
176
177 Hashtable response = new Hashtable();
178
179 response["int_response_code"] = 500;
180 response["str_response_string"] = "Script timeout";
181 response["content_type"] = "text/plain";
182 response["keepalive"] = false;
183 response["reusecontext"] = false;
184
185 return response;
186 };
187 }
188
189 public void Process()
190 {
191 Hashtable request = null;
192
193 try
194 {
195 lock (this.requests)
196 {
197 request = requests[0];
198 requests.RemoveAt(0);
199 }
200 }
201 catch
202 {
203 return;
204 }
205
206 UUID requestID = new UUID(request["RequestID"].ToString());
207
208 Hashtable response = new Hashtable();
209
210 response["int_response_code"] = 200;
211 response["content_type"] = "text/plain";
212 response["keepalive"] = false;
213 response["reusecontext"] = false;
214
215 response["str_response_string"] = m_webFetchHandler.FetchInventoryDescendentsRequest(request["body"].ToString(), String.Empty, String.Empty, null, null);
216
217 responses[requestID] = response;
218 }
219 }
220
114 private void RegisterCaps(UUID agentID, Caps caps) 221 private void RegisterCaps(UUID agentID, Caps caps)
115 { 222 {
116 string capUrl = "/CAPS/" + UUID.Random() + "/"; 223 string capUrl = "/CAPS/" + UUID.Random() + "/";
117 224
118 // Register this as a poll service 225 // Register this as a poll service
119 // absurd large timeout to tune later to make a bit less than viewer 226 // absurd large timeout to tune later to make a bit less than viewer
120 PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, agentID, 300000); 227 PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(agentID);
121 228
122 args.Type = PollServiceEventArgs.EventType.Inventory; 229 args.Type = PollServiceEventArgs.EventType.Inventory;
123 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); 230 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
@@ -135,8 +242,6 @@ namespace OpenSim.Region.ClientStack.Linden
135 caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl)); 242 caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
136 243
137 m_capsDict[agentID] = capUrl; 244 m_capsDict[agentID] = capUrl;
138
139 m_busy = false;
140 } 245 }
141 246
142 private void DeregisterCaps(UUID agentID, Caps caps) 247 private void DeregisterCaps(UUID agentID, Caps caps)
@@ -150,83 +255,14 @@ namespace OpenSim.Region.ClientStack.Linden
150 } 255 }
151 } 256 }
152 257
153 public void HttpRequestHandler(UUID requestID, Hashtable request) 258 private void DoInventoryRequests()
154 { 259 {
155// m_log.DebugFormat("[FETCH2]: Received request {0}", requestID); 260 while (true)
156 lock(m_lock)
157 m_requests[requestID] = request;
158 }
159
160 private bool HasEvents(UUID requestID, UUID sessionID)
161 {
162 lock (m_lock)
163 { 261 {
164 return !m_busy; 262 PollServiceInventoryEventArgs args = m_queue.Dequeue();
165 }
166 }
167
168 private Hashtable NoEvents(UUID requestID, UUID sessionID)
169 {
170 lock(m_lock)
171 m_requests.Remove(requestID);
172
173 Hashtable response = new Hashtable();
174
175 response["int_response_code"] = 500;
176 response["str_response_string"] = "Script timeout";
177 response["content_type"] = "text/plain";
178 response["keepalive"] = false;
179 response["reusecontext"] = false;
180
181 lock (m_lock)
182 m_busy = false;
183 263
184 return response; 264 args.Process();
185 }
186
187 private Hashtable GetEvents(UUID requestID, UUID sessionID, string request)
188 {
189 lock (m_lock)
190 m_busy = true;
191
192 Hashtable response = new Hashtable();
193
194 response["int_response_code"] = 500;
195 response["str_response_string"] = "Internal error";
196 response["content_type"] = "text/plain";
197 response["keepalive"] = false;
198 response["reusecontext"] = false;
199
200 try
201 {
202
203 Hashtable requestHash;
204 lock (m_lock)
205 {
206 if (!m_requests.TryGetValue(requestID, out requestHash))
207 {
208 m_busy = false;
209 response["str_response_string"] = "Invalid request";
210 return response;
211 }
212 m_requests.Remove(requestID);
213 }
214
215// m_log.DebugFormat("[FETCH2]: Processed request {0}", requestID);
216
217 string reply = m_webFetchHandler.FetchInventoryDescendentsRequest(requestHash["body"].ToString(), String.Empty, String.Empty, null, null);
218
219
220 response["int_response_code"] = 200;
221 response["str_response_string"] = reply;
222 }
223 finally
224 {
225 lock (m_lock)
226 m_busy = false;
227 } 265 }
228
229 return response;
230 } 266 }
231 } 267 }
232} 268}