1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.jetty;
16
17 import java.io.IOException;
18
19 import org.mortbay.io.AsyncEndPoint;
20 import org.mortbay.io.EndPoint;
21 import org.mortbay.log.Log;
22 import org.mortbay.thread.Timeout;
23
24 public class Suspendable
25 {
26
27 private static final int __IDLE=0;
28 private static final int __HANDLING=1;
29 private static final int __SUSPENDING=2;
30 private static final int __RESUMING=3;
31 private static final int __COMPLETING=4;
32 private static final int __SUSPENDED=5;
33 private static final int __UNSUSPENDING=6;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 protected HttpConnection _connection;
66
67 protected int _state;
68 protected boolean _initial;
69 protected boolean _resumed;
70 protected boolean _timeout;
71
72 protected long _timeoutMs;
73 protected final Timeout.Task _timeoutTask;
74
75
76
77 public Suspendable(HttpConnection connection)
78 {
79 _connection=connection;
80 _state=__IDLE;
81 _initial=true;
82 _resumed=false;
83
84 _timeoutTask= new Timeout.Task()
85 {
86 public void expired()
87 {
88 Suspendable.this.expire();
89 }
90 };
91 }
92
93
94
95
96 public long getTimeout()
97 {
98 return _timeoutMs;
99 }
100
101
102
103
104
105
106
107 public boolean isInitial()
108 {
109 synchronized(this)
110 {
111 return _initial;
112 }
113 }
114
115
116
117
118
119 public boolean isResumed()
120 {
121 synchronized(this)
122 {
123 return _resumed;
124 }
125 }
126
127
128
129
130
131 public boolean isSuspended()
132 {
133 synchronized(this)
134 {
135 switch(_state)
136 {
137 case __IDLE:
138 case __HANDLING:
139 return false;
140 case __SUSPENDING:
141 case __RESUMING:
142 case __COMPLETING:
143 case __SUSPENDED:
144 return true;
145 case __UNSUSPENDING:
146 default:
147 return false;
148 }
149 }
150 }
151
152
153
154
155
156
157 public boolean isTimeout()
158 {
159 synchronized(this)
160 {
161 return _timeout;
162 }
163 }
164
165
166
167
168
169
170 public void suspend()
171 {
172 long timeout = 30000L;
173 suspend(timeout);
174 }
175
176
177 public String toString()
178 {
179 return getStatusString();
180 }
181
182
183 public String getStatusString()
184 {
185 synchronized (this)
186 {
187 return
188 ((_state==__IDLE)?"IDLE":
189 (_state==__HANDLING)?"HANDLING":
190 (_state==__SUSPENDING)?"SUSPENDING":
191 (_state==__SUSPENDED)?"SUSPENDED":
192 (_state==__RESUMING)?"RESUMING":
193 (_state==__UNSUSPENDING)?"UNSUSPENDING":
194 (_state==__COMPLETING)?"COMPLETING":
195 ("???"+_state))+
196 (_initial?",initial":"")+
197 (_resumed?",resumed":"")+
198 (_timeout?",timeout":"");
199 }
200 }
201
202
203
204
205
206 public void handling()
207 {
208 synchronized (this)
209 {
210 switch(_state)
211 {
212 case __HANDLING:
213 throw new IllegalStateException(this.getStatusString());
214
215 case __IDLE:
216 _initial=true;
217 _state=__HANDLING;
218 return;
219
220 case __SUSPENDING:
221 case __RESUMING:
222 throw new IllegalStateException(this.getStatusString());
223
224 case __COMPLETING:
225 return;
226
227 case __SUSPENDED:
228 cancelTimeout();
229 case __UNSUSPENDING:
230 _state=__HANDLING;
231 return;
232
233 default:
234 throw new IllegalStateException(""+_state);
235 }
236
237 }
238 }
239
240
241
242
243
244 public void suspend(long timeoutMs)
245 {
246 synchronized (this)
247 {
248 switch(_state)
249 {
250 case __HANDLING:
251 _timeout=false;
252 _resumed=false;
253 _state=__SUSPENDING;
254 _timeoutMs = timeoutMs;
255 return;
256
257 case __IDLE:
258 throw new IllegalStateException(this.getStatusString());
259
260 case __SUSPENDING:
261 case __RESUMING:
262 if (timeoutMs<_timeoutMs)
263 _timeoutMs = timeoutMs;
264 return;
265
266 case __COMPLETING:
267 case __SUSPENDED:
268 case __UNSUSPENDING:
269 throw new IllegalStateException(this.getStatusString());
270
271 default:
272 throw new IllegalStateException(""+_state);
273 }
274
275 }
276 }
277
278
279
280
281
282
283 public boolean unhandling()
284 {
285 synchronized (this)
286 {
287 switch(_state)
288 {
289 case __HANDLING:
290 _state=__IDLE;
291 return true;
292
293 case __IDLE:
294 throw new IllegalStateException(this.getStatusString());
295
296 case __SUSPENDING:
297 _initial=false;
298 _state=__SUSPENDED;
299 scheduleTimeout();
300 if (_state==__SUSPENDED || _state==__COMPLETING)
301 return true;
302 _initial=false;
303 _state=__HANDLING;
304 return false;
305
306 case __RESUMING:
307 _initial=false;
308 _state=__HANDLING;
309 return false;
310
311 case __COMPLETING:
312 _initial=false;
313 _state=__IDLE;
314 return true;
315
316 case __SUSPENDED:
317 case __UNSUSPENDING:
318 default:
319 throw new IllegalStateException(this.getStatusString());
320
321 }
322
323 }
324 }
325
326
327 public void resume()
328 {
329 boolean dispatch=false;
330 synchronized (this)
331 {
332 switch(_state)
333 {
334 case __HANDLING:
335 _resumed=true;
336 return;
337
338 case __SUSPENDING:
339 _resumed=true;
340 _state=__RESUMING;
341 return;
342
343 case __IDLE:
344 case __RESUMING:
345 case __COMPLETING:
346 return;
347
348 case __SUSPENDED:
349 dispatch=true;
350 _resumed=true;
351 _state=__UNSUSPENDING;
352 break;
353
354 case __UNSUSPENDING:
355 _resumed=true;
356 return;
357
358 default:
359 throw new IllegalStateException(this.getStatusString());
360 }
361 }
362
363 if (dispatch)
364 {
365 cancelTimeout();
366 scheduleDispatch();
367 }
368 }
369
370
371
372 protected void expire()
373 {
374
375 boolean dispatch=false;
376 synchronized (this)
377 {
378 switch(_state)
379 {
380 case __HANDLING:
381 return;
382
383 case __IDLE:
384 throw new IllegalStateException(this.getStatusString());
385
386 case __SUSPENDING:
387 _timeout=true;
388 _state=__RESUMING;
389 cancelTimeout();
390 return;
391
392 case __RESUMING:
393 return;
394
395 case __COMPLETING:
396 return;
397
398 case __SUSPENDED:
399 dispatch=true;
400 _timeout=true;
401 _state=__UNSUSPENDING;
402 break;
403
404 case __UNSUSPENDING:
405 _timeout=true;
406 return;
407
408 default:
409 throw new IllegalStateException(this.getStatusString());
410 }
411 }
412 if (dispatch)
413 {
414 scheduleDispatch();
415 }
416 }
417
418
419
420
421
422 public void complete() throws IOException
423 {
424
425 boolean dispatch=false;
426 synchronized (this)
427 {
428 switch(_state)
429 {
430 case __HANDLING:
431 throw new IllegalStateException(this.getStatusString());
432
433 case __IDLE:
434 return;
435
436 case __SUSPENDING:
437 _state=__COMPLETING;
438 break;
439
440 case __RESUMING:
441 break;
442
443 case __COMPLETING:
444 return;
445
446 case __SUSPENDED:
447 _state=__COMPLETING;
448 dispatch=true;
449 break;
450
451 case __UNSUSPENDING:
452 return;
453
454 default:
455 throw new IllegalStateException(this.getStatusString());
456 }
457 }
458
459 if (dispatch)
460 {
461 cancelTimeout();
462 scheduleDispatch();
463 }
464 }
465
466
467
468 public void reset()
469 {
470 synchronized (this)
471 {
472 _state=(_state==__SUSPENDED||_state==__IDLE)?__IDLE:__HANDLING;
473 _resumed = false;
474 _initial = true;
475 _timeout = false;
476 cancelTimeout();
477 }
478 }
479
480
481 protected void scheduleDispatch()
482 {
483 EndPoint endp=_connection.getEndPoint();
484 if (!endp.isBlocking())
485 {
486 ((AsyncEndPoint)endp).dispatch();
487 }
488 }
489
490
491 protected void scheduleTimeout()
492 {
493 EndPoint endp=_connection.getEndPoint();
494 if (endp.isBlocking())
495 {
496 synchronized(this)
497 {
498 long expire_at = System.currentTimeMillis()+_timeoutMs;
499 long wait=_timeoutMs;
500 while (_timeoutMs>0 && wait>0)
501 {
502 try
503 {
504 this.wait(wait);
505 }
506 catch (InterruptedException e)
507 {
508 Log.ignore(e);
509 }
510 wait=expire_at-System.currentTimeMillis();
511 }
512
513 if (_timeoutMs>0 && wait<=0)
514 expire();
515 }
516
517 }
518 else
519 _connection.scheduleTimeout(_timeoutTask,_timeoutMs);
520 }
521
522
523 protected void cancelTimeout()
524 {
525 EndPoint endp=_connection.getEndPoint();
526 if (endp.isBlocking())
527 {
528 synchronized(this)
529 {
530 _timeoutMs=0;
531 this.notifyAll();
532 }
533 }
534 else
535 _connection.cancelTimeout(_timeoutTask);
536 }
537
538
539 public boolean isCompleting()
540 {
541 return _state==__COMPLETING;
542 }
543
544
545 public boolean shouldHandleRequest()
546 {
547 switch(_state)
548 {
549 case __COMPLETING:
550 return false;
551
552 default:
553 return true;
554 }
555 }
556
557
558 public boolean shouldComplete()
559 {
560 switch(_state)
561 {
562 case __RESUMING:
563 case __SUSPENDED:
564 case __SUSPENDING:
565 case __UNSUSPENDING:
566 return false;
567
568 default:
569 return true;
570 }
571 }
572
573 }