11
11
12
12
import org .elasticsearch .common .bytes .CompositeBytesReference ;
13
13
import org .elasticsearch .common .bytes .ReleasableBytesReference ;
14
+ import org .elasticsearch .core .CheckedConsumer ;
14
15
import org .elasticsearch .core .Releasable ;
15
16
import org .elasticsearch .core .Releasables ;
16
17
17
18
import java .io .IOException ;
18
19
import java .util .ArrayDeque ;
19
- import java .util .ArrayList ;
20
20
import java .util .function .BiConsumer ;
21
21
import java .util .function .LongSupplier ;
22
22
23
23
public class InboundPipeline implements Releasable {
24
24
25
- private static final ThreadLocal <ArrayList <Object >> fragmentList = ThreadLocal .withInitial (ArrayList ::new );
26
25
private static final InboundMessage PING_MESSAGE = new InboundMessage (null , true );
27
26
28
27
private final LongSupplier relativeTimeInMillis ;
@@ -56,81 +55,74 @@ public void close() {
56
55
57
56
public void handleBytes (TcpChannel channel , ReleasableBytesReference reference ) throws IOException {
58
57
if (uncaughtException != null ) {
58
+ reference .close ();
59
59
throw new IllegalStateException ("Pipeline state corrupted by uncaught exception" , uncaughtException );
60
60
}
61
61
try {
62
- doHandleBytes (channel , reference );
62
+ channel .getChannelStats ().markAccessed (relativeTimeInMillis .getAsLong ());
63
+ statsTracker .markBytesRead (reference .length ());
64
+ if (isClosed ) {
65
+ reference .close ();
66
+ return ;
67
+ }
68
+ pending .add (reference );
69
+ doHandleBytes (channel );
63
70
} catch (Exception e ) {
64
71
uncaughtException = e ;
65
72
throw e ;
66
73
}
67
74
}
68
75
69
- public void doHandleBytes (TcpChannel channel , ReleasableBytesReference reference ) throws IOException {
70
- channel .getChannelStats ().markAccessed (relativeTimeInMillis .getAsLong ());
71
- statsTracker .markBytesRead (reference .length ());
72
- pending .add (reference .retain ());
73
-
74
- final ArrayList <Object > fragments = fragmentList .get ();
75
- boolean continueHandling = true ;
76
-
77
- while (continueHandling && isClosed == false ) {
78
- boolean continueDecoding = true ;
79
- while (continueDecoding && pending .isEmpty () == false ) {
80
- try (ReleasableBytesReference toDecode = getPendingBytes ()) {
81
- final int bytesDecoded = decoder .decode (toDecode , fragments ::add );
82
- if (bytesDecoded != 0 ) {
83
- releasePendingBytes (bytesDecoded );
84
- if (fragments .isEmpty () == false && endOfMessage (fragments .get (fragments .size () - 1 ))) {
85
- continueDecoding = false ;
86
- }
87
- } else {
88
- continueDecoding = false ;
89
- }
76
+ private void doHandleBytes (TcpChannel channel ) throws IOException {
77
+ do {
78
+ CheckedConsumer <Object , IOException > decodeConsumer = f -> forwardFragment (channel , f );
79
+ int bytesDecoded = decoder .decode (pending .peekFirst (), decodeConsumer );
80
+ if (bytesDecoded == 0 && pending .size () > 1 ) {
81
+ final ReleasableBytesReference [] bytesReferences = new ReleasableBytesReference [pending .size ()];
82
+ int index = 0 ;
83
+ for (ReleasableBytesReference pendingReference : pending ) {
84
+ bytesReferences [index ] = pendingReference .retain ();
85
+ ++index ;
86
+ }
87
+ try (
88
+ ReleasableBytesReference toDecode = new ReleasableBytesReference (
89
+ CompositeBytesReference .of (bytesReferences ),
90
+ () -> Releasables .closeExpectNoException (bytesReferences )
91
+ )
92
+ ) {
93
+ bytesDecoded = decoder .decode (toDecode , decodeConsumer );
90
94
}
91
95
}
92
-
93
- if (fragments .isEmpty ()) {
94
- continueHandling = false ;
96
+ if (bytesDecoded != 0 ) {
97
+ releasePendingBytes (bytesDecoded );
95
98
} else {
96
- try {
97
- forwardFragments (channel , fragments );
98
- } finally {
99
- for (Object fragment : fragments ) {
100
- if (fragment instanceof ReleasableBytesReference ) {
101
- ((ReleasableBytesReference ) fragment ).close ();
102
- }
103
- }
104
- fragments .clear ();
105
- }
99
+ break ;
106
100
}
107
- }
101
+ } while ( pending . isEmpty () == false );
108
102
}
109
103
110
- private void forwardFragments (TcpChannel channel , ArrayList <Object > fragments ) throws IOException {
111
- for (Object fragment : fragments ) {
112
- if (fragment instanceof Header ) {
113
- headerReceived ((Header ) fragment );
114
- } else if (fragment instanceof Compression .Scheme ) {
115
- assert aggregator .isAggregating ();
116
- aggregator .updateCompressionScheme ((Compression .Scheme ) fragment );
117
- } else if (fragment == InboundDecoder .PING ) {
118
- assert aggregator .isAggregating () == false ;
119
- messageHandler .accept (channel , PING_MESSAGE );
120
- } else if (fragment == InboundDecoder .END_CONTENT ) {
121
- assert aggregator .isAggregating ();
122
- InboundMessage aggregated = aggregator .finishAggregation ();
123
- try {
124
- statsTracker .markMessageReceived ();
125
- messageHandler .accept (channel , aggregated );
126
- } finally {
127
- aggregated .decRef ();
128
- }
129
- } else {
130
- assert aggregator .isAggregating ();
131
- assert fragment instanceof ReleasableBytesReference ;
132
- aggregator .aggregate ((ReleasableBytesReference ) fragment );
104
+ private void forwardFragment (TcpChannel channel , Object fragment ) throws IOException {
105
+ if (fragment instanceof Header ) {
106
+ headerReceived ((Header ) fragment );
107
+ } else if (fragment instanceof Compression .Scheme ) {
108
+ assert aggregator .isAggregating ();
109
+ aggregator .updateCompressionScheme ((Compression .Scheme ) fragment );
110
+ } else if (fragment == InboundDecoder .PING ) {
111
+ assert aggregator .isAggregating () == false ;
112
+ messageHandler .accept (channel , PING_MESSAGE );
113
+ } else if (fragment == InboundDecoder .END_CONTENT ) {
114
+ assert aggregator .isAggregating ();
115
+ InboundMessage aggregated = aggregator .finishAggregation ();
116
+ try {
117
+ statsTracker .markMessageReceived ();
118
+ messageHandler .accept (channel , aggregated );
119
+ } finally {
120
+ aggregated .decRef ();
133
121
}
122
+ } else {
123
+ assert aggregator .isAggregating ();
124
+ assert fragment instanceof ReleasableBytesReference ;
125
+ aggregator .aggregate ((ReleasableBytesReference ) fragment );
134
126
}
135
127
}
136
128
@@ -139,25 +131,6 @@ protected void headerReceived(Header header) {
139
131
aggregator .headerReceived (header );
140
132
}
141
133
142
- private static boolean endOfMessage (Object fragment ) {
143
- return fragment == InboundDecoder .PING || fragment == InboundDecoder .END_CONTENT || fragment instanceof Exception ;
144
- }
145
-
146
- private ReleasableBytesReference getPendingBytes () {
147
- if (pending .size () == 1 ) {
148
- return pending .peekFirst ().retain ();
149
- } else {
150
- final ReleasableBytesReference [] bytesReferences = new ReleasableBytesReference [pending .size ()];
151
- int index = 0 ;
152
- for (ReleasableBytesReference pendingReference : pending ) {
153
- bytesReferences [index ] = pendingReference .retain ();
154
- ++index ;
155
- }
156
- final Releasable releasable = () -> Releasables .closeExpectNoException (bytesReferences );
157
- return new ReleasableBytesReference (CompositeBytesReference .of (bytesReferences ), releasable );
158
- }
159
- }
160
-
161
134
private void releasePendingBytes (int bytesConsumed ) {
162
135
int bytesToRelease = bytesConsumed ;
163
136
while (bytesToRelease != 0 ) {
0 commit comments