1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.fcgi.generator;
20
21 import java.nio.ByteBuffer;
22 import java.util.ArrayDeque;
23 import java.util.Queue;
24
25 import org.eclipse.jetty.io.EndPoint;
26 import org.eclipse.jetty.util.IteratingCallback;
27 import org.eclipse.jetty.util.log.Log;
28 import org.eclipse.jetty.util.log.Logger;
29
30 public class Flusher
31 {
32 private static final Logger LOG = Log.getLogger(Flusher.class);
33
34 private final Queue<Generator.Result> queue = new ArrayDeque<>();
35 private final IteratingCallback flushCallback = new FlushCallback();
36 private final EndPoint endPoint;
37
38 public Flusher(EndPoint endPoint)
39 {
40 this.endPoint = endPoint;
41 }
42
43 public void flush(Generator.Result... results)
44 {
45 for (Generator.Result result : results)
46 offer(result);
47 flushCallback.iterate();
48 }
49
50 private void offer(Generator.Result result)
51 {
52 synchronized (this)
53 {
54 queue.offer(result);
55 }
56 }
57
58 private Generator.Result poll()
59 {
60 synchronized (this)
61 {
62 return queue.poll();
63 }
64 }
65
66 public void shutdown()
67 {
68 flush(new ShutdownResult());
69 }
70
71 private class FlushCallback extends IteratingCallback
72 {
73 private Generator.Result active;
74
75 @Override
76 protected Action process() throws Exception
77 {
78
79 Generator.Result result = poll();
80 if (result == null)
81 {
82
83 return Action.IDLE;
84 }
85
86
87
88
89
90 Generator.Result other = poll();
91 if (other != null)
92 result = result.join(other);
93
94 active = result;
95 ByteBuffer[] buffers = result.getByteBuffers();
96 endPoint.write(this, buffers);
97 return Action.SCHEDULED;
98 }
99
100 @Override
101 protected void onCompleteSuccess()
102 {
103
104 throw new IllegalStateException();
105 }
106
107 @Override
108 public void succeeded()
109 {
110 if (active != null)
111 active.succeeded();
112 active = null;
113 super.succeeded();
114 }
115
116 @Override
117 public void onCompleteFailure(Throwable x)
118 {
119 if (active != null)
120 active.failed(x);
121 active = null;
122
123 while (true)
124 {
125 Generator.Result result = poll();
126 if (result == null)
127 break;
128 result.failed(x);
129 }
130 }
131 }
132
133 private class ShutdownResult extends Generator.Result
134 {
135 private ShutdownResult()
136 {
137 super(null, null);
138 }
139
140 @Override
141 public void succeeded()
142 {
143 shutdown();
144 }
145
146 @Override
147 public void failed(Throwable x)
148 {
149 shutdown();
150 }
151
152 private void shutdown()
153 {
154 if (LOG.isDebugEnabled())
155 LOG.debug("Shutting down {}", endPoint);
156 endPoint.shutdownOutput();
157 }
158 }
159 }