Skip to content

Commit 76ccc51

Browse files
committed
if a bulk insert is too big for 1 buffer, break it up JAVA-66
1 parent e69e2e5 commit 76ccc51

File tree

3 files changed

+73
-19
lines changed

3 files changed

+73
-19
lines changed

src/main/com/mongodb/ByteEncoder.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,14 +172,19 @@ public int putObject( DBObject o ){
172172
}
173173
catch ( BufferOverflowException bof ){
174174
reset();
175-
throw new IllegalArgumentException( "tried to save too large of an object. max size : " + ( _buf.capacity() / 2 ) );
175+
throw getTooLargeException();
176176
}
177177
}
178178

179+
RuntimeException getTooLargeException(){
180+
return new IllegalArgumentException( "tried to save too large of an object. " +
181+
" max size : " + ( _buf.capacity() / 2 ) );
182+
}
183+
179184
/**
180185
* this is really for embedded objects
181186
*/
182-
private int putObject( String name , DBObject o ){
187+
int putObject( String name , DBObject o ){
183188
if ( o == null )
184189
throw new NullPointerException( "can't save a null object" );
185190

src/main/com/mongodb/DBApiLayer.java

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -181,27 +181,42 @@ protected DBObject[] insert(DBObject[] arr, boolean shouldApply )
181181
((ObjectId)id)._new = false;
182182
}
183183
}
184-
185-
ByteEncoder encoder = ByteEncoder.get();
186-
187-
encoder._buf.putInt( 0 ); // reserved
188-
encoder._put( _fullNameSpace );
189-
190-
for (DBObject o : arr) {
191-
encoder.putObject( o );
192-
}
193-
encoder.flip();
194-
195-
try {
196-
doInsert( encoder._buf , getWriteConcern() );
197-
}
198-
finally {
199-
encoder.done();
184+
185+
int cur = 0;
186+
while ( cur < arr.length ){
187+
ByteEncoder encoder = ByteEncoder.get();
188+
189+
encoder._buf.putInt( 0 ); // reserved
190+
encoder._put( _fullNameSpace );
191+
192+
int n=0;
193+
for ( ; cur<arr.length; cur++ ){
194+
DBObject o = arr[cur];
195+
int pos = encoder._buf.position();
196+
try {
197+
encoder.putObject( null , o );
198+
n++;
199+
}
200+
catch ( BufferOverflowException e ){
201+
if ( n == 0 )
202+
throw encoder.getTooLargeException();
203+
encoder._buf.position( pos );
204+
break;
205+
}
206+
}
207+
encoder.flip();
208+
209+
try {
210+
doInsert( encoder._buf , getWriteConcern() );
211+
}
212+
finally {
213+
encoder.done();
214+
}
200215
}
201216

202217
return arr;
203218
}
204-
219+
205220
public void remove( DBObject o )
206221
throws MongoException {
207222

src/test/com/mongodb/JavaClientTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,40 @@ public void testObjectIdCompat2(){
441441
}
442442

443443

444+
@Test
445+
public void testLargeBulkInsert(){
446+
DBCollection c = _db.getCollection( "largebulk" );
447+
c.drop();
448+
String s = "asdasdasd";
449+
while ( s.length() < 10000 )
450+
s += s;
451+
List<DBObject> l = new ArrayList<DBObject>();
452+
final int num = 3 * ( Bytes.MAX_OBJECT_SIZE / s.length() );
453+
454+
for ( int i=0; i<num; i++ ){
455+
l.add( BasicDBObjectBuilder.start()
456+
.add( "_id" , i )
457+
.add( "x" , s )
458+
.get() );
459+
}
460+
assertEquals( 0 , c.find().count() );
461+
c.insert( l );
462+
assertEquals( num , c.find().count() );
463+
464+
s = l.toString();
465+
assertTrue( s.length() > Bytes.MAX_OBJECT_SIZE );
466+
467+
boolean worked = false;
468+
try {
469+
c.save( new BasicDBObject( "foo" , s ) );
470+
worked = true;
471+
}
472+
catch ( IllegalArgumentException ie ){}
473+
assertFalse( worked );
474+
475+
assertEquals( num , c.find().count() );
476+
}
477+
444478

445479
final Mongo _mongo;
446480
final DB _db;

0 commit comments

Comments
 (0)