2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
4
4
using System ;
5
- using System . Buffers . Binary ;
6
5
using System . Collections . Concurrent ;
7
- using System . IO ;
8
6
using System . Threading ;
9
7
using Microsoft . Build . Internal ;
10
8
using Microsoft . Build . Shared ;
11
- #if ! FEATURE_APM
12
9
using System . Threading . Tasks ;
13
- #endif
14
10
15
11
namespace Microsoft . Build . BackEnd . Client
16
12
{
@@ -46,25 +42,15 @@ internal sealed class MSBuildClientPacketPump : INodePacketHandler, INodePacketF
46
42
/// </summary>
47
43
private readonly NodePacketFactory _packetFactory ;
48
44
49
- /// <summary>
50
- /// The memory stream for a read buffer.
51
- /// </summary>
52
- private readonly MemoryStream _readBufferMemoryStream ;
53
-
54
45
/// <summary>
55
46
/// The thread which runs the asynchronous packet pump
56
47
/// </summary>
57
48
private Thread ? _packetPumpThread ;
58
49
59
50
/// <summary>
60
- /// The stream from where to read packets.
61
- /// </summary>
62
- private readonly Stream _stream ;
63
-
64
- /// <summary>
65
- /// The binary translator for reading packets.
51
+ /// The pipe client from where to read packets.
66
52
/// </summary>
67
- private readonly ITranslator _binaryReadTranslator ;
53
+ private readonly NodePipeClient _pipeClient ;
68
54
69
55
/// <summary>
70
56
/// True if this side is gracefully disconnecting.
@@ -73,21 +59,19 @@ internal sealed class MSBuildClientPacketPump : INodePacketHandler, INodePacketF
73
59
/// </summary>
74
60
private bool _isServerDisconnecting ;
75
61
76
- public MSBuildClientPacketPump ( Stream stream )
62
+ public MSBuildClientPacketPump ( NodePipeClient pipeClient )
77
63
{
78
- ErrorUtilities . VerifyThrowArgumentNull ( stream ) ;
64
+ ErrorUtilities . VerifyThrowArgumentNull ( pipeClient ) ;
79
65
80
- _stream = stream ;
66
+ _pipeClient = pipeClient ;
67
+ _pipeClient . RegisterPacketFactory ( this ) ;
81
68
_isServerDisconnecting = false ;
82
69
_packetFactory = new NodePacketFactory ( ) ;
83
70
84
71
ReceivedPacketsQueue = new ConcurrentQueue < INodePacket > ( ) ;
85
72
PacketReceivedEvent = new AutoResetEvent ( false ) ;
86
73
PacketPumpCompleted = new ManualResetEvent ( false ) ;
87
74
_packetPumpShutdownEvent = new ManualResetEvent ( false ) ;
88
-
89
- _readBufferMemoryStream = new MemoryStream ( ) ;
90
- _binaryReadTranslator = BinaryTranslator . GetReadTranslator ( _readBufferMemoryStream , InterningBinaryReader . CreateSharedBuffer ( ) ) ;
91
75
}
92
76
93
77
#region INodePacketFactory Members
@@ -113,14 +97,13 @@ public void UnregisterPacketHandler(NodePacketType packetType)
113
97
}
114
98
115
99
/// <summary>
116
- /// Deserializes and routes a packer to the appropriate handler .
100
+ /// Deserializes a packet .
117
101
/// </summary>
118
- /// <param name="nodeId">The node from which the packet was received.</param>
119
102
/// <param name="packetType">The packet type.</param>
120
103
/// <param name="translator">The translator to use as a source for packet data.</param>
121
- public void DeserializeAndRoutePacket ( int nodeId , NodePacketType packetType , ITranslator translator )
104
+ public INodePacket DeserializePacket ( NodePacketType packetType , ITranslator translator )
122
105
{
123
- _packetFactory . DeserializeAndRoutePacket ( nodeId , packetType , translator ) ;
106
+ return _packetFactory . DeserializePacket ( packetType , translator ) ;
124
107
}
125
108
126
109
/// <summary>
@@ -182,21 +165,16 @@ public void Stop()
182
165
/// </remarks>
183
166
private void PacketPumpProc ( )
184
167
{
185
- RunReadLoop ( _stream , _packetPumpShutdownEvent ) ;
168
+ RunReadLoop ( _pipeClient , _packetPumpShutdownEvent ) ;
186
169
}
187
170
188
- private void RunReadLoop ( Stream localStream , ManualResetEvent localPacketPumpShutdownEvent )
171
+ private void RunReadLoop ( NodePipeClient pipeClient , ManualResetEvent localPacketPumpShutdownEvent )
189
172
{
190
173
CommunicationsUtilities . Trace ( "Entering read loop." ) ;
191
174
192
175
try
193
176
{
194
- byte [ ] headerByte = new byte [ 5 ] ;
195
- #if FEATURE_APM
196
- IAsyncResult result = localStream . BeginRead ( headerByte , 0 , headerByte . Length , null , null ) ;
197
- #else
198
- Task < int > readTask = CommunicationsUtilities . ReadAsync ( localStream , headerByte , headerByte . Length ) . AsTask ( ) ;
199
- #endif
177
+ Task < INodePacket > readTask = pipeClient . ReadPacketAsync ( ) ;
200
178
201
179
bool continueReading = true ;
202
180
do
@@ -208,11 +186,7 @@ private void RunReadLoop(Stream localStream, ManualResetEvent localPacketPumpShu
208
186
WaitHandle [ ] handles =
209
187
[
210
188
localPacketPumpShutdownEvent ,
211
- #if FEATURE_APM
212
- result . AsyncWaitHandle
213
- #else
214
189
( ( IAsyncResult ) readTask ) . AsyncWaitHandle
215
- #endif
216
190
] ;
217
191
int waitId = WaitHandle . WaitAny ( handles ) ;
218
192
switch ( waitId )
@@ -224,80 +198,27 @@ private void RunReadLoop(Stream localStream, ManualResetEvent localPacketPumpShu
224
198
break ;
225
199
226
200
case 1 :
201
+ INodePacket packet = readTask . GetAwaiter ( ) . GetResult ( ) ;
202
+
203
+ if ( packet . Type == NodePacketType . NodeShutdown )
227
204
{
228
- // Client recieved a packet header. Read the rest of it.
229
- int headerBytesRead = 0 ;
230
- #if FEATURE_APM
231
- headerBytesRead = localStream . EndRead ( result ) ;
232
- #else
233
- headerBytesRead = readTask . Result ;
234
- #endif
235
-
236
- if ( ( headerBytesRead != headerByte . Length ) && ! localPacketPumpShutdownEvent . WaitOne ( 0 ) )
205
+ if ( ! _isServerDisconnecting )
237
206
{
238
- // Incomplete read. Abort.
239
- if ( headerBytesRead == 0 )
240
- {
241
- if ( _isServerDisconnecting )
242
- {
243
- continueReading = false ;
244
- break ;
245
- }
246
-
247
- ErrorUtilities . ThrowInternalError ( "Server disconnected abruptly" ) ;
248
- }
249
- else
250
- {
251
- ErrorUtilities . ThrowInternalError ( "Incomplete header read. {0} of {1} bytes read" , headerBytesRead , headerByte . Length ) ;
252
- }
207
+ ErrorUtilities . ThrowInternalError ( "Server disconnected abruptly." ) ;
253
208
}
254
209
255
- NodePacketType packetType = ( NodePacketType ) Enum . ToObject ( typeof ( NodePacketType ) , headerByte [ 0 ] ) ;
256
-
257
- int packetLength = BinaryPrimitives . ReadInt32LittleEndian ( new Span < byte > ( headerByte , 1 , 4 ) ) ;
258
- int packetBytesRead = 0 ;
259
-
260
- _readBufferMemoryStream . Position = 0 ;
261
- _readBufferMemoryStream . SetLength ( packetLength ) ;
262
- byte [ ] packetData = _readBufferMemoryStream . GetBuffer ( ) ;
263
-
264
- while ( packetBytesRead < packetLength )
265
- {
266
- int bytesRead = localStream . Read ( packetData , packetBytesRead , packetLength - packetBytesRead ) ;
267
- if ( bytesRead == 0 )
268
- {
269
- // Incomplete read. Abort.
270
- ErrorUtilities . ThrowInternalError ( "Incomplete packet read. {0} of {1} bytes read" , packetBytesRead , packetLength ) ;
271
- }
272
-
273
- packetBytesRead += bytesRead ;
274
- }
210
+ continueReading = false ;
211
+ break ;
212
+ }
275
213
276
- try
277
- {
278
- _packetFactory . DeserializeAndRoutePacket ( 0 , packetType , _binaryReadTranslator ) ;
279
- }
280
- catch
281
- {
282
- // Error while deserializing or handling packet. Logging additional info.
283
- CommunicationsUtilities . Trace ( "Packet factory failed to receive package. Exception while deserializing packet {0}." , packetType ) ;
284
- throw ;
285
- }
214
+ _packetFactory . RoutePacket ( 0 , packet ) ;
286
215
287
- if ( packetType == NodePacketType . ServerNodeBuildResult )
288
- {
289
- continueReading = false ;
290
- }
291
- else
292
- {
293
- // Start reading the next package header.
294
- #if FEATURE_APM
295
- result = localStream . BeginRead ( headerByte , 0 , headerByte . Length , null , null ) ;
296
- #else
297
- readTask = CommunicationsUtilities . ReadAsync ( localStream , headerByte , headerByte . Length ) . AsTask ( ) ;
298
- #endif
299
- }
216
+ continueReading = packet . Type != NodePacketType . ServerNodeBuildResult ;
217
+ if ( continueReading )
218
+ {
219
+ readTask = pipeClient . ReadPacketAsync ( ) ;
300
220
}
221
+
301
222
break ;
302
223
303
224
default :
0 commit comments