1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.client;
20
21 import java.util.concurrent.TimeUnit;
22 import java.util.concurrent.TimeoutException;
23 import java.util.concurrent.atomic.AtomicReference;
24
25 import org.eclipse.jetty.client.api.Request;
26 import org.eclipse.jetty.client.api.Response;
27 import org.eclipse.jetty.client.api.Result;
28 import org.eclipse.jetty.util.log.Log;
29 import org.eclipse.jetty.util.log.Logger;
30 import org.eclipse.jetty.util.thread.Scheduler;
31
32 public class TimeoutCompleteListener implements Response.CompleteListener, Runnable
33 {
34 private static final Logger LOG = Log.getLogger(TimeoutCompleteListener.class);
35
36 private final AtomicReference<Scheduler.Task> task = new AtomicReference<>();
37 private final Request request;
38
39 public TimeoutCompleteListener(Request request)
40 {
41 this.request = request;
42 }
43
44 @Override
45 public void onComplete(Result result)
46 {
47 cancel();
48 }
49
50 public boolean schedule(Scheduler scheduler)
51 {
52 long timeout = request.getTimeout();
53 Scheduler.Task task = scheduler.schedule(this, timeout, TimeUnit.MILLISECONDS);
54 Scheduler.Task existing = this.task.getAndSet(task);
55 if (existing != null)
56 {
57 existing.cancel();
58 cancel();
59 throw new IllegalStateException();
60 }
61 if (LOG.isDebugEnabled())
62 LOG.debug("Scheduled timeout task {} in {} ms for {}", task, timeout, request);
63 return true;
64 }
65
66 @Override
67 public void run()
68 {
69 if (LOG.isDebugEnabled())
70 LOG.debug("Executing timeout task {} for {}", task, request);
71 request.abort(new TimeoutException("Total timeout elapsed"));
72 }
73
74 public void cancel()
75 {
76 Scheduler.Task task = this.task.getAndSet(null);
77 if (task != null)
78 {
79 boolean cancelled = task.cancel();
80 if (LOG.isDebugEnabled())
81 LOG.debug("Cancelled (successfully: {}) timeout task {}", cancelled, task);
82 }
83 }
84 }