1
1
/**
2
2
* Copyright (c) 2002-2016 "Neo Technology,"
3
3
* Network Engine for Objects in Lund AB [http://neotechnology.com]
4
- *
4
+ * <p>
5
5
* This file is part of Neo4j.
6
- *
6
+ * <p>
7
7
* Licensed under the Apache License, Version 2.0 (the "License");
8
8
* you may not use this file except in compliance with the License.
9
9
* You may obtain a copy of the License at
10
- *
11
- * http://www.apache.org/licenses/LICENSE-2.0
12
- *
10
+ * <p>
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ * <p>
13
13
* Unless required by applicable law or agreed to in writing, software
14
14
* distributed under the License is distributed on an "AS IS" BASIS,
15
15
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -100,8 +100,11 @@ public State readChunkSize( BufferingChunkedInput ctx ) throws IOException
100
100
{
101
101
if ( ctx .buffer .remaining () == 0 )
102
102
{
103
- //buffer empty, read next packet and try again
104
- readNextPacket ( ctx .channel , ctx .buffer );
103
+ //buffer empty, block until you get at least at least one byte
104
+ while ( ctx .buffer .remaining () == 0 )
105
+ {
106
+ readNextPacket ( ctx .channel , ctx .buffer );
107
+ }
105
108
return AWAITING_CHUNK .readChunkSize ( ctx );
106
109
}
107
110
else if ( ctx .buffer .remaining () >= 2 )
@@ -132,7 +135,7 @@ public State read( BufferingChunkedInput ctx ) throws IOException
132
135
public State peekByte ( BufferingChunkedInput ctx ) throws IOException
133
136
{
134
137
//read chunk size and then proceed to read the rest of the chunk.
135
- return readChunkSize ( ctx ).peekByte ( ctx );
138
+ return readChunkSize ( ctx ).peekByte ( ctx );
136
139
}
137
140
},
138
141
IN_CHUNK
@@ -175,7 +178,7 @@ else if ( ctx.buffer.remaining() < ctx.scratchBuffer.remaining() )
175
178
int bytesToRead = min ( ctx .scratchBuffer .remaining (), ctx .remainingChunkSize );
176
179
copyBytes ( ctx .buffer , ctx .scratchBuffer , bytesToRead );
177
180
ctx .remainingChunkSize -= bytesToRead ;
178
- if (ctx .scratchBuffer .remaining () == 0 )
181
+ if ( ctx .scratchBuffer .remaining () == 0 )
179
182
{
180
183
//we have written all data that was asked for us
181
184
return IN_CHUNK ;
@@ -229,7 +232,7 @@ public State readChunkSize( BufferingChunkedInput ctx ) throws IOException
229
232
}
230
233
231
234
@ Override
232
- public State read ( BufferingChunkedInput ctx ) throws IOException
235
+ public State read ( BufferingChunkedInput ctx ) throws IOException
233
236
{
234
237
throw new IllegalStateException ( "Cannot read data while in progress of reading header" );
235
238
}
@@ -271,25 +274,34 @@ public State peekByte( BufferingChunkedInput ctx ) throws IOException
271
274
* @param buffer The buffer to read into
272
275
* @throws IOException
273
276
*/
274
- private static void readNextPacket (ReadableByteChannel channel , ByteBuffer buffer ) throws IOException
277
+ private static void readNextPacket ( ReadableByteChannel channel , ByteBuffer buffer ) throws IOException
275
278
{
276
279
try
277
280
{
278
281
buffer .clear ();
279
- channel .read ( buffer );
282
+ int read = channel .read ( buffer );
283
+ if ( read == -1 )
284
+ {
285
+ throw new ClientException (
286
+ "Connection terminated while receiving data. This can happen due to network " +
287
+ "instabilities, or due to restarts of the database." );
288
+ }
280
289
buffer .flip ();
281
290
}
282
- catch ( ClosedByInterruptException e )
291
+ catch ( ClosedByInterruptException e )
283
292
{
284
293
throw new ClientException (
285
- "Connection to the database was lost because someone called `interrupt()` on the driver thread waiting for a reply. " +
286
- "This normally happens because the JVM is shutting down, but it can also happen because your application code or some " +
294
+ "Connection to the database was lost because someone called `interrupt()` on the driver " +
295
+ "thread waiting for a reply. " +
296
+ "This normally happens because the JVM is shutting down, but it can also happen because your " +
297
+ "application code or some " +
287
298
"framework you are using is manually interrupting the thread." );
288
299
}
289
300
catch ( IOException e )
290
301
{
291
302
String message = e .getMessage () == null ? e .getClass ().getSimpleName () : e .getMessage ();
292
- throw new ClientException ( "Unable to process request: " + message + " buffer: \n " + BytePrinter .hex ( buffer ), e );
303
+ throw new ClientException (
304
+ "Unable to process request: " + message + " buffer: \n " + BytePrinter .hex ( buffer ), e );
293
305
}
294
306
}
295
307
@@ -368,7 +380,7 @@ public PackInput readBytes( byte[] into, int offset, int toRead ) throws IOExcep
368
380
public byte peekByte () throws IOException
369
381
{
370
382
state = state .peekByte ( this );
371
- return buffer .get (buffer .position ());
383
+ return buffer .get ( buffer .position () );
372
384
}
373
385
374
386
private boolean hasMoreDataUnreadInCurrentChunk ()
@@ -382,7 +394,7 @@ private boolean hasMoreDataUnreadInCurrentChunk()
382
394
public void run ()
383
395
{
384
396
// the on message complete should only be called when no data unread from the message buffer
385
- if ( hasMoreDataUnreadInCurrentChunk () )
397
+ if ( hasMoreDataUnreadInCurrentChunk () )
386
398
{
387
399
throw new ClientException ( "Trying to read message complete ending '00 00' while there are more data " +
388
400
"left in the message content unread: buffer [" +
@@ -392,11 +404,12 @@ public void run()
392
404
try
393
405
{
394
406
// read message boundary
395
- state .readChunkSize ( BufferingChunkedInput .this );
407
+ state .readChunkSize ( BufferingChunkedInput .this );
396
408
if ( remainingChunkSize != 0 )
397
409
{
398
410
throw new ClientException ( "Expecting message complete ending '00 00', but got " +
399
- BytePrinter .hex ( ByteBuffer .allocate ( 2 ).putShort ( (short ) remainingChunkSize ) ) );
411
+ BytePrinter .hex ( ByteBuffer .allocate ( 2 )
412
+ .putShort ( (short ) remainingChunkSize ) ) );
400
413
}
401
414
}
402
415
catch ( IOException e )
0 commit comments