Skip to content

Commit 9910c35

Browse files
author
Brendan W. McAdams
committed
JAVA-505 / JAVA-421 - Regression in performance of Java Driver should be rolled back
1 parent b51ca14 commit 9910c35

File tree

4 files changed

+291
-273
lines changed

4 files changed

+291
-273
lines changed

src/main/org/bson/BasicBSONDecoder.java

Lines changed: 238 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
import java.io.*;
2121

22-
import org.bson.io.BSONInput;
2322
import org.bson.io.PoolOutputBuffer;
2423
import org.bson.types.ObjectId;
2524

@@ -283,7 +282,245 @@ Object _readBasicObject()
283282
}
284283

285284

285+
286+
protected class BSONInput {
287+
288+
public BSONInput(InputStream in){
289+
_raw = in;
290+
_read = 0;
291+
292+
_pos = 0;
293+
_len = 0;
294+
}
295+
296+
/**
297+
* ensure that there are num bytes to read
298+
* _pos is where to start reading from
299+
* @return where to start reading from
300+
*/
301+
protected int _need( final int num )
302+
throws IOException {
303+
304+
//System.out.println( "p: " + _pos + " l: " + _len + " want: " + num );
305+
306+
if ( _len - _pos >= num ){
307+
final int ret = _pos;
308+
_pos += num;
309+
_read += num;
310+
return ret;
311+
}
312+
313+
if ( num >= _inputBuffer.length )
314+
throw new IllegalArgumentException( "you can't need that much" );
315+
316+
final int remaining = _len - _pos;
317+
if ( _pos > 0 ){
318+
System.arraycopy( _inputBuffer , _pos , _inputBuffer , 0 , remaining );
319+
320+
_pos = 0;
321+
_len = remaining;
322+
}
323+
324+
// read as much as possible into buffer
325+
int maxToRead = Math.min( _max - _read - remaining , _inputBuffer.length - _len );
326+
while ( maxToRead > 0 ){
327+
int x = _raw.read( _inputBuffer , _len , maxToRead);
328+
if ( x <= 0 )
329+
throw new IOException( "unexpected EOF" );
330+
maxToRead -= x;
331+
_len += x;
332+
}
333+
334+
int ret = _pos;
335+
_pos += num;
336+
_read += num;
337+
return ret;
338+
}
339+
340+
public int readInt()
341+
throws IOException {
342+
return org.bson.io.Bits.readInt( _inputBuffer , _need(4) );
343+
}
344+
345+
public int readIntBE()
346+
throws IOException {
347+
return org.bson.io.Bits.readIntBE( _inputBuffer , _need(4) );
348+
}
349+
350+
public long readLong()
351+
throws IOException {
352+
return org.bson.io.Bits.readLong( _inputBuffer , _need(8) );
353+
}
354+
355+
public double readDouble()
356+
throws IOException {
357+
return Double.longBitsToDouble( readLong() );
358+
}
359+
360+
public byte read()
361+
throws IOException {
362+
if ( _pos < _len ){
363+
++_read;
364+
return _inputBuffer[_pos++];
365+
}
366+
return _inputBuffer[_need(1)];
367+
}
368+
369+
public void fill( byte b[] )
370+
throws IOException {
371+
fill( b , b.length );
372+
}
373+
374+
public void fill( byte b[] , int len )
375+
throws IOException {
376+
// first use what we have
377+
int have = _len - _pos;
378+
int tocopy = Math.min( len , have );
379+
System.arraycopy( _inputBuffer , _pos , b , 0 , tocopy );
380+
381+
_pos += tocopy;
382+
_read += tocopy;
383+
384+
len -= tocopy;
385+
386+
int off = tocopy;
387+
while ( len > 0 ){
388+
int x = _raw.read( b , off , len );
389+
if (x <= 0)
390+
throw new IOException( "unexpected EOF" );
391+
_read += x;
392+
off += x;
393+
len -= x;
394+
}
395+
}
396+
397+
protected boolean _isAscii( byte b ){
398+
return b >=0 && b <= 127;
399+
}
400+
401+
public String readCStr()
402+
throws IOException {
403+
404+
boolean isAscii = true;
405+
406+
// short circuit 1 byte strings
407+
_random[0] = read();
408+
if (_random[0] == 0) {
409+
return "";
410+
}
411+
412+
_random[1] = read();
413+
if (_random[1] == 0) {
414+
String out = ONE_BYTE_STRINGS[_random[0]];
415+
if (out != null) {
416+
return out;
417+
}
418+
return new String(_random, 0, 1, "UTF-8");
419+
}
420+
421+
_stringBuffer.reset();
422+
_stringBuffer.write(_random[0]);
423+
_stringBuffer.write(_random[1]);
424+
425+
isAscii = _isAscii(_random[0]) && _isAscii(_random[1]);
426+
427+
while ( true ){
428+
byte b = read();
429+
if ( b == 0 )
430+
break;
431+
_stringBuffer.write( b );
432+
isAscii = isAscii && _isAscii( b );
433+
}
434+
435+
String out = null;
436+
if ( isAscii ){
437+
out = _stringBuffer.asAscii();
438+
}
439+
else {
440+
try {
441+
out = _stringBuffer.asString( "UTF-8" );
442+
}
443+
catch ( UnsupportedOperationException e ){
444+
throw new BSONException( "impossible" , e );
445+
}
446+
}
447+
_stringBuffer.reset();
448+
return out;
449+
}
450+
451+
public String readUTF8String()
452+
throws IOException {
453+
int size = readInt();
454+
// this is just protection in case it's corrupted, to avoid huge strings
455+
if ( size <= 0 || size > ( 32 * 1024 * 1024 ) )
456+
throw new BSONException( "bad string size: " + size );
457+
458+
if ( size < _inputBuffer.length / 2 ){
459+
if ( size == 1 ){
460+
read();
461+
return "";
462+
}
463+
464+
return new String( _inputBuffer , _need(size) , size - 1 , "UTF-8" );
465+
}
466+
467+
byte[] b = size < _random.length ? _random : new byte[size];
468+
469+
fill( b , size );
470+
471+
try {
472+
return new String( b , 0 , size - 1 , "UTF-8" );
473+
}
474+
catch ( java.io.UnsupportedEncodingException uee ){
475+
throw new BSONException( "impossible" , uee );
476+
}
477+
}
478+
479+
public int numRead() {
480+
return _read;
481+
}
482+
483+
public int getPos() {
484+
return _pos;
485+
}
486+
487+
public int getMax() {
488+
return _max;
489+
}
490+
491+
public void setMax(int _max) {
492+
this._max = _max;
493+
}
494+
495+
int _read;
496+
final InputStream _raw;
497+
498+
int _max = 4; // max number of total bytes allowed to ready
499+
500+
}
286501
protected BSONInput _in;
287502
protected BSONCallback _callback;
503+
private byte[] _random = new byte[1024]; // has to be used within a single function
504+
private byte[] _inputBuffer = new byte[1024];
505+
private PoolOutputBuffer _stringBuffer = new PoolOutputBuffer();
288506

507+
protected int _pos; // current offset into _inputBuffer
508+
protected int _len; // length of valid data in _inputBuffer
509+
510+
511+
512+
static final String[] ONE_BYTE_STRINGS = new String[128];
513+
static void _fillRange( byte min, byte max ){
514+
while ( min < max ){
515+
String s = "";
516+
s += (char)min;
517+
ONE_BYTE_STRINGS[(int)min] = s;
518+
min++;
519+
}
520+
}
521+
static {
522+
_fillRange( (byte)'0' , (byte)'9' );
523+
_fillRange( (byte)'a' , (byte)'z' );
524+
_fillRange( (byte)'A' , (byte)'Z' );
525+
}
289526
}

0 commit comments

Comments
 (0)