aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Servers/HttpServer
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Servers/HttpServer')
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs24
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs175
2 files changed, 120 insertions, 79 deletions
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index e1ae74e..e243002 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -113,7 +113,7 @@ namespace OpenSim.Framework.Servers.HttpServer
113 113
114 protected IPAddress m_listenIPAddress = IPAddress.Any; 114 protected IPAddress m_listenIPAddress = IPAddress.Any;
115 115
116 private PollServiceRequestManager m_PollServiceManager; 116 public PollServiceRequestManager PollServiceRequestManager { get; private set; }
117 117
118 public uint SSLPort 118 public uint SSLPort
119 { 119 {
@@ -374,7 +374,7 @@ namespace OpenSim.Framework.Servers.HttpServer
374 return true; 374 return true;
375 } 375 }
376 376
377 private void OnRequest(object source, RequestEventArgs args) 377 public void OnRequest(object source, RequestEventArgs args)
378 { 378 {
379 RequestNumber++; 379 RequestNumber++;
380 380
@@ -429,7 +429,7 @@ namespace OpenSim.Framework.Servers.HttpServer
429 psEvArgs.Request(psreq.RequestID, keysvals); 429 psEvArgs.Request(psreq.RequestID, keysvals);
430 } 430 }
431 431
432 m_PollServiceManager.Enqueue(psreq); 432 PollServiceRequestManager.Enqueue(psreq);
433 } 433 }
434 else 434 else
435 { 435 {
@@ -1781,10 +1781,17 @@ namespace OpenSim.Framework.Servers.HttpServer
1781 1781
1782 public void Start() 1782 public void Start()
1783 { 1783 {
1784 StartHTTP(); 1784 Start(true);
1785 } 1785 }
1786 1786
1787 private void StartHTTP() 1787 /// <summary>
1788 /// Start the http server
1789 /// </summary>
1790 /// <param name='processPollRequestsAsync'>
1791 /// If true then poll responses are performed asynchronsly.
1792 /// Option exists to allow regression tests to perform processing synchronously.
1793 /// </param>
1794 public void Start(bool performPollResponsesAsync)
1788 { 1795 {
1789 m_log.InfoFormat( 1796 m_log.InfoFormat(
1790 "[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port); 1797 "[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port);
@@ -1822,8 +1829,9 @@ namespace OpenSim.Framework.Servers.HttpServer
1822 m_httpListener2.Start(64); 1829 m_httpListener2.Start(64);
1823 1830
1824 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events 1831 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events
1825 m_PollServiceManager = new PollServiceRequestManager(this, 3, 25000); 1832 PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 3, 25000);
1826 m_PollServiceManager.Start(); 1833 PollServiceRequestManager.Start();
1834
1827 HTTPDRunning = true; 1835 HTTPDRunning = true;
1828 1836
1829 //HttpListenerContext context; 1837 //HttpListenerContext context;
@@ -1892,7 +1900,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1892 1900
1893 try 1901 try
1894 { 1902 {
1895 m_PollServiceManager.Stop(); 1903 PollServiceRequestManager.Stop();
1896 1904
1897 m_httpListener2.ExceptionThrown -= httpServerException; 1905 m_httpListener2.ExceptionThrown -= httpServerException;
1898 //m_httpListener2.DisconnectHandler = null; 1906 //m_httpListener2.DisconnectHandler = null;
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index 6aa5907..456acb0 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -44,6 +44,20 @@ namespace OpenSim.Framework.Servers.HttpServer
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 /// <summary>
48 /// Is the poll service request manager running?
49 /// </summary>
50 /// <remarks>
51 /// Can be running either synchronously or asynchronously
52 /// </remarks>
53 public bool IsRunning { get; private set; }
54
55 /// <summary>
56 /// Is the poll service performing responses asynchronously (with its own threads) or synchronously (via
57 /// external calls)?
58 /// </summary>
59 public bool PerformResponsesAsync { get; private set; }
60
47 private readonly BaseHttpServer m_server; 61 private readonly BaseHttpServer m_server;
48 62
49 private BlockingQueue<PollServiceHttpRequest> m_requests = new BlockingQueue<PollServiceHttpRequest>(); 63 private BlockingQueue<PollServiceHttpRequest> m_requests = new BlockingQueue<PollServiceHttpRequest>();
@@ -52,48 +66,53 @@ namespace OpenSim.Framework.Servers.HttpServer
52 private uint m_WorkerThreadCount = 0; 66 private uint m_WorkerThreadCount = 0;
53 private Thread[] m_workerThreads; 67 private Thread[] m_workerThreads;
54 68
55 private bool m_running = true;
56
57 private SmartThreadPool m_threadPool = new SmartThreadPool(20000, 12, 2); 69 private SmartThreadPool m_threadPool = new SmartThreadPool(20000, 12, 2);
58 70
59// private int m_timeout = 1000; // increase timeout 250; now use the event one 71// private int m_timeout = 1000; // increase timeout 250; now use the event one
60 72
61 public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout) 73 public PollServiceRequestManager(
74 BaseHttpServer pSrv, bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout)
62 { 75 {
63 m_server = pSrv; 76 m_server = pSrv;
77 PerformResponsesAsync = performResponsesAsync;
64 m_WorkerThreadCount = pWorkerThreadCount; 78 m_WorkerThreadCount = pWorkerThreadCount;
65 m_workerThreads = new Thread[m_WorkerThreadCount]; 79 m_workerThreads = new Thread[m_WorkerThreadCount];
66 } 80 }
67 81
68 public void Start() 82 public void Start()
69 { 83 {
70 //startup worker threads 84 IsRunning = true;
71 for (uint i = 0; i < m_WorkerThreadCount; i++) 85
86 if (PerformResponsesAsync)
72 { 87 {
73 m_workerThreads[i] 88 //startup worker threads
74 = Watchdog.StartThread( 89 for (uint i = 0; i < m_WorkerThreadCount; i++)
75 PoolWorkerJob, 90 {
76 string.Format("PollServiceWorkerThread{0}:{1}", i, m_server.Port), 91 m_workerThreads[i]
77 ThreadPriority.Normal, 92 = Watchdog.StartThread(
78 false, 93 PoolWorkerJob,
79 false, 94 string.Format("PollServiceWorkerThread{0}:{1}", i, m_server.Port),
80 null, 95 ThreadPriority.Normal,
81 int.MaxValue); 96 false,
82 } 97 false,
98 null,
99 int.MaxValue);
100 }
83 101
84 Watchdog.StartThread( 102 Watchdog.StartThread(
85 this.CheckLongPollThreads, 103 this.CheckLongPollThreads,
86 string.Format("LongPollServiceWatcherThread:{0}", m_server.Port), 104 string.Format("LongPollServiceWatcherThread:{0}", m_server.Port),
87 ThreadPriority.Normal, 105 ThreadPriority.Normal,
88 false, 106 false,
89 true, 107 true,
90 null, 108 null,
91 1000 * 60 * 10); 109 1000 * 60 * 10);
110 }
92 } 111 }
93 112
94 private void ReQueueEvent(PollServiceHttpRequest req) 113 private void ReQueueEvent(PollServiceHttpRequest req)
95 { 114 {
96 if (m_running) 115 if (IsRunning)
97 { 116 {
98 // delay the enqueueing for 100ms. There's no need to have the event 117 // delay the enqueueing for 100ms. There's no need to have the event
99 // actively on the queue 118 // actively on the queue
@@ -109,7 +128,7 @@ namespace OpenSim.Framework.Servers.HttpServer
109 128
110 public void Enqueue(PollServiceHttpRequest req) 129 public void Enqueue(PollServiceHttpRequest req)
111 { 130 {
112 if (m_running) 131 if (IsRunning)
113 { 132 {
114 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll) 133 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll)
115 { 134 {
@@ -129,7 +148,7 @@ namespace OpenSim.Framework.Servers.HttpServer
129 // All other types of tasks (Inventory handlers, http-in, etc) don't have the long-poll nature, 148 // All other types of tasks (Inventory handlers, http-in, etc) don't have the long-poll nature,
130 // so if they aren't ready to be served by a worker thread (no events), they are placed 149 // so if they aren't ready to be served by a worker thread (no events), they are placed
131 // directly back in the "ready-to-serve" queue by the worker thread. 150 // directly back in the "ready-to-serve" queue by the worker thread.
132 while (m_running) 151 while (IsRunning)
133 { 152 {
134 Thread.Sleep(500); 153 Thread.Sleep(500);
135 Watchdog.UpdateThread(); 154 Watchdog.UpdateThread();
@@ -137,7 +156,7 @@ namespace OpenSim.Framework.Servers.HttpServer
137// List<PollServiceHttpRequest> not_ready = new List<PollServiceHttpRequest>(); 156// List<PollServiceHttpRequest> not_ready = new List<PollServiceHttpRequest>();
138 lock (m_longPollRequests) 157 lock (m_longPollRequests)
139 { 158 {
140 if (m_longPollRequests.Count > 0 && m_running) 159 if (m_longPollRequests.Count > 0 && IsRunning)
141 { 160 {
142 List<PollServiceHttpRequest> ready = m_longPollRequests.FindAll(req => 161 List<PollServiceHttpRequest> ready = m_longPollRequests.FindAll(req =>
143 (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id) || // there are events in this EQ 162 (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id) || // there are events in this EQ
@@ -158,7 +177,7 @@ namespace OpenSim.Framework.Servers.HttpServer
158 177
159 public void Stop() 178 public void Stop()
160 { 179 {
161 m_running = false; 180 IsRunning = false;
162// m_timeout = -10000; // cause all to expire 181// m_timeout = -10000; // cause all to expire
163 Thread.Sleep(1000); // let the world move 182 Thread.Sleep(1000); // let the world move
164 183
@@ -169,7 +188,7 @@ namespace OpenSim.Framework.Servers.HttpServer
169 188
170 lock (m_longPollRequests) 189 lock (m_longPollRequests)
171 { 190 {
172 if (m_longPollRequests.Count > 0 && m_running) 191 if (m_longPollRequests.Count > 0 && IsRunning)
173 m_longPollRequests.ForEach(req => m_requests.Enqueue(req)); 192 m_longPollRequests.ForEach(req => m_requests.Enqueue(req));
174 } 193 }
175 194
@@ -194,68 +213,82 @@ namespace OpenSim.Framework.Servers.HttpServer
194 213
195 private void PoolWorkerJob() 214 private void PoolWorkerJob()
196 { 215 {
197 while (m_running) 216 while (IsRunning)
198 { 217 {
199 PollServiceHttpRequest req = m_requests.Dequeue(5000);
200 //m_log.WarnFormat("[YYY]: Dequeued {0}", (req == null ? "null" : req.PollServiceArgs.Type.ToString()));
201
202 Watchdog.UpdateThread(); 218 Watchdog.UpdateThread();
203 if (req != null) 219 WaitPerformResponse();
220 }
221 }
222
223 public void WaitPerformResponse()
224 {
225 PollServiceHttpRequest req = m_requests.Dequeue(5000);
226// m_log.DebugFormat("[YYY]: Dequeued {0}", (req == null ? "null" : req.PollServiceArgs.Type.ToString()));
227
228 if (req != null)
229 {
230 try
204 { 231 {
205 try 232 if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
206 { 233 {
207 if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id)) 234 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
208 {
209 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
210 235
211 if (responsedata == null) 236 if (responsedata == null)
212 continue; 237 return;
213 238
214 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll) // This is the event queue 239 // This is the event queue.
240 // Even if we're not running we can still perform responses by explicit request.
241 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll
242 || !PerformResponsesAsync)
243 {
244 try
245 {
246 req.DoHTTPGruntWork(m_server, responsedata);
247 }
248 catch (ObjectDisposedException e) // Browser aborted before we could read body, server closed the stream
249 {
250 // Ignore it, no need to reply
251 m_log.Error(e);
252 }
253 }
254 else
255 {
256 m_threadPool.QueueWorkItem(x =>
215 { 257 {
216 try 258 try
217 { 259 {
218 req.DoHTTPGruntWork(m_server, responsedata); 260 req.DoHTTPGruntWork(m_server, responsedata);
219 } 261 }
220 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream 262 catch (ObjectDisposedException e) // Browser aborted before we could read body, server closed the stream
221 { 263 {
222 // Ignore it, no need to reply 264 // Ignore it, no need to reply
265 m_log.Error(e);
223 } 266 }
224 } 267 catch (Exception e)
225 else
226 {
227 m_threadPool.QueueWorkItem(x =>
228 { 268 {
229 try 269 m_log.Error(e);
230 { 270 }
231 req.DoHTTPGruntWork(m_server, responsedata); 271
232 } 272 return null;
233 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream 273 }, null);
234 { 274 }
235 // Ignore it, no need to reply 275 }
236 } 276 else
237 277 {
238 return null; 278 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
239 }, null); 279 {
240 } 280 req.DoHTTPGruntWork(
281 m_server, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
241 } 282 }
242 else 283 else
243 { 284 {
244 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) 285 ReQueueEvent(req);
245 {
246 req.DoHTTPGruntWork(
247 m_server, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
248 }
249 else
250 {
251 ReQueueEvent(req);
252 }
253 } 286 }
254 } 287 }
255 catch (Exception e) 288 }
256 { 289 catch (Exception e)
257 m_log.ErrorFormat("Exception in poll service thread: " + e.ToString()); 290 {
258 } 291 m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
259 } 292 }
260 } 293 }
261 } 294 }